git.fiddlerwoaroof.com
Raw Blame History
;; -*- mode: Emacs-Lisp;tab-width: 8;indent-tabs-mode: nil; -*-
(setq gc-cons-threshold 100000000
      inhibit-splash-screen t
      inhibit-startup-message t)

(let ((my-theme-path (expand-file-name "~/.emacs.d/themes/")))
  (add-to-list 'load-path my-theme-path)
  (add-to-list 'custom-theme-load-path my-theme-path)
  (load-theme 'fwoar-zenburn t))

(progn (setq default-frame-alist
             '((vertical-scroll-bars . nil)
               (right-divider-width . 2)
               (bottom-divider-width . 2)))
       (modify-all-frames-parameters default-frame-alist))

(let ((my-theme-path (expand-file-name "~/.emacs.d/themes/")))
  (add-to-list 'load-path my-theme-path)
  (add-to-list 'custom-theme-load-path my-theme-path)
  (load-theme 'fwoar-zenburn t))

(tool-bar-mode 0)
(scroll-bar-mode 0)

(message invocation-name)

(let ((default-directory  "~/.emacs.d/lisp/"))
  (make-directory default-directory t)
  (add-to-list 'load-path (expand-file-name default-directory))
  (normal-top-level-add-subdirs-to-load-path)
  (load "utils"))

(cold-boot)
(load "site-lisp")
(load-package-configuration 'evil)


;;(use-package multifiles
;;  :config
;;  (define-key evil-visual-state-map " m" 'mf/mirror-region-in-multifile)
;;  )

(use-package org
  :pin "org"
  :ensure t
  :config
  (setq org-directory "~/org"
        org-default-notes-file (concat org-directory "/scratch.org")
        org-refile-use-outline-path 'file
        org-outline-path-complete-in-steps nil
        org-log-done 'time
        org-capture-templates '(("t" "Todo" entry (file+headline "~/org/gtd.org" "Tasks")
                                 "* TODO %?\n  %i\n  %a")
                                ("j" "Journal" entry (file+olp+datetree "~/org/journal.org")
                                 "* %?\nEntered on %U\n  %i\n  %a")
                                ("s" "Snippet" entry (file "~/org/snippets.org")
                                 "* %?\n#+BEGIN_SRC\n%i\n#+END_SRC")
                                ("b" "Bookmarks" entry (file+olp+datetree "~/org/bookmarks.org")
                                 "* %? %^g\n%c\n"))
        org-refile-targets '((nil . (:maxlevel . 2))))

  (org-babel-do-load-languages
   'org-babel-load-languages
   '((lisp . t)))

  (define-key global-map "\C-cc" 'org-capture)
  (define-key evil-visual-state-map " c" 'org-capture))

(use-package org-projectile
  :ensure t
  :config
  (progn
    (org-projectile-per-project)
    (setq org-agenda-skip-unavailable-files t)
    (setq org-projectile-per-project-filepath
          "notes/README.org")
    (setq org-agenda-files (append org-agenda-files (org-projectile-todo-files)))
    (push (org-projectile-project-todo-entry) org-capture-templates)
    (define-key projectile-mode-map (kbd "C-c c") 'org-capture))
  :ensure t)

(use-package org-projectile-helm
  :ensure t
  :after org-projectile
  :config
  (define-key projectile-mode-map (kbd "C-c n p") 'org-projectile-helm-template-or-project))

(use-package deadgrep
  :ensure t)

(use-package deft
  :ensure t
  :config
  (define-key evil-normal-state-map " v" 'deft))

(use-package emmet-mode
  :ensure t
  :config
  (define-key evil-insert-state-map (kbd "C-c ,") 'emmet-expand-line))

(use-package company
  :config
  ;; keybindings
  (progn (define-key company-active-map (kbd "C-c h") 'company-quickhelp-manual-begin)
         (define-key company-active-map (kbd "(") (kbd "RET SPC ("))
         (define-key company-active-map (kbd "{") (kbd "RET SPC {"))
         (define-key company-active-map (kbd "[") (kbd "RET [")))

  (setq company-backends
        '(company-clang
          company-bbdb
          company-nxml
          company-css
          company-xcode
          company-cmake
          company-capf
          company-slime
          company-files
          (company-dabbrev-code
           company-gtags
           company-etags
           company-keywords)
          company-oddmuse
          company-dabbrev)))

(use-package company-posframe
  :ensure t
  :after company
  :config
  (add-hook 'company-mode-hook (lambda () (company-posframe-mode 1))))

(use-package lisp-skeletons
  :config
  (add-hook 'skeleton-end-hook 'skeleton-make-markers)

  (define-key evil-insert-state-map (kbd "C-c j") 'skeleton-next-position)
  (define-key evil-insert-state-map (kbd "C-c k") 'skeleton-prev-position)
  (define-key evil-normal-state-map " g" 'helm-generate-lisp-skeleton)
  (define-key evil-visual-state-map " g" 'helm-generate-lisp-skeleton))



(use-package js2-mode
  :ensure t
  :defer t
  :commands js2-mode
  :config
  (modify-syntax-entry ?_ "w" js2-mode-syntax-table)
  (add-to-list 'interpreter-mode-alist (cons "node" 'js2-mode))
  (setq-default js2-basic-offset 4)
  (setq-default js-indent-level 4)
  (add-hook 'js2-mode-hook 'flycheck-mode)
  (customize-set-variable 'js2-mode-show-parse-errors nil)
  (customize-set-variable 'js2-strict-missing-semi-warning nil)
  (customize-set-variable 'js2-strict-trailing-comma-warning nil)
  (customize-set-variable 'js2-strict-inconsistent-return-warning nil))

(use-package js
  :ensure t
  :config
  (modify-syntax-entry ?_ "w" js-mode-syntax-table)

  ;;; indent ternaries with arrow function correctly---
  (defun js--looking-at-operator-p ()
    "Return non-nil if point is on a JavaScript operator, other than a comma."
    (save-match-data
      (and (looking-at js--indent-operator-re)
           (or (not (eq (char-after) ?:))
               (save-excursion
                 (js--backward-syntactic-ws)
                 (when (memq (char-before) '(?\) ?})) (backward-list))
                 (and (js--re-search-backward "[?:{]\\|\\_<case\\_>" nil t)
                      (eq (char-after) ??))))
           (not (and
                 (eq (char-after) ?/)
                 (save-excursion
                   (eq (nth 3 (syntax-ppss)) ?/))))
           (not (and
                 (eq (char-after) ?*)
                 ;; Generator method (possibly using computed property).
                 (looking-at (concat "\\* *\\(?:\\[\\|" js--name-re " *(\\)"))
                 (save-excursion
                   (js--backward-syntactic-ws)
                   ;; We might misindent some expressions that would
                   ;; return NaN anyway.  Shouldn't be a problem.
                   (memq (char-before) '(?, ?} ?{)))))))))

(use-package vue-mode
  :config
  (add-hook 'vue-mode
            'prettier-js-mode)
  (add-hook 'vue-mode
            'flycheck-mode))

(use-package prettier-js
  :ensure t
  :init
  (add-hook 'js2-mode-hook 'prettier-js-mode))

(use-package tide
  :ensure t
  :config
  (add-hook 'js2-mode-hook 'tide-setup)
  (add-hook 'js2-mode-hook 'tide-hl-identifier-mode)
  (flycheck-add-next-checker 'javascript-eslint 'javascript-tide 'append))

(use-package rjsx-mode
  :ensure t
  :config
  (add-to-list 'auto-mode-alist '("\\.js$" . rjsx-mode)))

(comment
 (use-package tern
   :config
   (add-hook 'js-mode-hook (lambda () (tern-mode t)))
   (add-hook 'js2-mode-hook (lambda () (tern-mode t)))))

(use-package company-tern
  :ensure t
  :config
  (add-to-list 'company-backends 'company-tern)
  (setq company-tooltip-align-annotations t))

(use-package jest
  :ensure t
  :config
  (defun jest--project-root ()
    "Find the project root directory."
    (let ((closest-package-json (fwoar--find-package-json))
          (projectile-root (projectile-project-root)))
      (message "%s <-> %s" closest-package-json projectile-root)
      (if (s-prefix-p projectile-root closest-package-json)
          closest-package-json
        projectile-root))))


(defun more-than-one-project-file-p ()
  (= (length (projectile-select-files (projectile-current-project-files)))
     1))

(defun global-find-known-file ())

(defun helm-find-known-file (&optional arg)
  "Use projectile with Helm for finding files in project

With a prefix ARG invalidates the cache first."
  (interactive "P")
  (let ((projectile-enable-caching t))
    (if (projectile-project-p)
        (projectile-maybe-invalidate-cache arg)
      (unless t
        (error "You're not in a project"))))
  (let ((helm-ff-transformer-show-only-basename nil)
        (helm-boring-file-regexp-list nil))
    (helm :sources 'helm-source-projectile-files-in-all-projects-list
          :buffer (concat "*helm projectile: "
                          (projectile-project-name)
                          "*")
          :truncate-lines helm-projectile-truncate-lines
          :prompt (projectile-prepend-project-name "Find file in projects: "))))

(defun project-aware-ffap (&rest args)
  (interactive "F")
  (apply (if (and (projectile-project-p)
                  (more-than-one-project-file-p))
             'helm-projectile-find-file-dwim
           'find-file-at-point)
         args))

(use-package projectile
  :ensure t
  :config
  (define-key evil-normal-state-map " h" 'helm-projectile-find-file-dwim)
  (setq
   ;;       projectile-enable-caching t
   projectile-generic-command "rg --files -0"
   )

  (projectile-register-project-type
   'clojure '("project.clj")
   :compile "lein uberjar"
   :test-dir "src/test/")

  (projectile-register-project-type
   'lisp '("*.asd"))
  
  (projectile-register-project-type
   'npm '("package.json")
   :compile "npm install"
   :test "npm test"
   :run "npm start"
   :test-suffix ".spec")

  (define-key evil-normal-state-map "gf" 'project-aware-ffap))


(use-package cl-generic
  :ensure t)

(defun intercept-print (f)
  (print f)
  f)

(cl-defmethod fwoar--find-system (&context (major-mode clojure-mode))
  (let ((systems (directory-files
                  (locate-dominating-file default-directory
                                          (lambda (n)
                                            (or (directory-files n nil "project.clj")
                                                (directory-files n nil "build.boot")
                                                (directory-files n nil "deps.edn")
                                                (directory-files n nil "shadow-cljs.edn"))))
                  t "^\\(project.clj\\|build.boot\\|deps.edn\\|shadow-cljs.edn\\)$")))
    (find-file (if (not (null (cdr systems)))
                   (helm-comp-read "system:" systems)
                 (car systems)))))

(cl-defgeneric fwoar--pl-selector ()
  (:method ()
           (slime-selector))

  (:method (&context (major-mode clojure-mode))
           (cider-selector))
  (:method (&context (projectile-project-type (eql :clojure)))
           (cider-selector))
  (:method (&context (major-mode cider-repl-mode))
           (cider-selector)))

(defun fwoar-pl-selector ()
  (interactive)
  (fwoar--pl-selector))
(define-key evil-normal-state-map " o" 'fwoar-pl-selector)


(use-package cider
  :ensure t
  :config
  (require 'cider-selector)
  (define-key evil-normal-state-map " t" 'cider-test-run-ns-tests)
  (evil-define-key 'normal clojure-mode-map " '" 'helm-cider-apropos)

  (def-cider-selector-method ?S "find clojure project file"
    (fwoar--find-system))

  (add-hook 'cider-mode-hook
            (lambda ()
              (flycheck-mode)
              (rainbow-delimiters-mode 1)
              (evil-smartparens-mode 1)
              (smartparens-strict-mode 1)
              (aggressive-indent-mode 1)
              (helm-cider-mode 1)
              (cider-company-enable-fuzzy-completion)))

  (add-hook 'cider-repl-mode-hook
            (lambda ()
              (rainbow-delimiters-mode 1)
              (evil-smartparens-mode 1)
              (smartparens-strict-mode 1)
              (aggressive-indent-mode 0)
              (helm-cider-mode 1)
              (cider-company-enable-fuzzy-completion)))

  (modify-syntax-entry ?_ "w" clojure-mode-syntax-table)
  (modify-syntax-entry ?- "w" clojure-mode-syntax-table)
  (modify-syntax-entry ?~ "w" clojure-mode-syntax-table)
  (modify-syntax-entry ?. "w" clojure-mode-syntax-table)

  (define-key cider-repl-mode-map (kbd "C-c M-o") 'cider-repl-clear-buffer)
  (define-key cider-repl-mode-map (kbd "C-c C-o") 'cider-repl-clear-output)
  (setq cider-save-file-on-load t
        cider-repl-history-file "~/.emacs.d/cider-history.clj")

  (defun cider-eval-expression-at-point-in-repl ()
    (interactive)
    (let ((form (cider-defun-at-point)))
      ;; Strip excess whitespace
      (while (string-match "\\`\s+\\|\n+\\'" form)
        (setq form (replace-match "" t t form)))
      (with-current-buffer (cider-current-repl nil t)
        (let ((fw/window (get-buffer-window)))
          (with-selected-window fw/window
            (end-of-buffer)
            (insert form)
            (cider-repl-return)
            (end-of-buffer))))))

  (define-key cider-mode-map
    (kbd "C-c C-j") 'cider-eval-expression-at-point-in-repl)

  ;; https://github.com/clojure-emacs/cider/issues/2435
  (defun cider--gather-session-params (session)
    "Gather all params for a SESSION."
    (let (params)
      (dolist (repl (cdr session))
        (when (buffer-name repl)
          (setq params (cider--gather-connect-params params repl))))
      (when-let* ((server (cider--session-server session)))
        (setq params (cider--gather-connect-params params server)))
      params))

  )

(use-package flycheck-clj-kondo
  :ensure t)



(use-package imenu
  :config
  (define-key evil-normal-state-map " d" 'helm-imenu-in-all-buffers))

(defun fwoar--paste-from-register-mru-buffer (register)
  (interactive
   (let ((overlay (make-overlay (point) (point)))
         (string "\""))
     (unwind-protect
         (progn
           ;; display " in the buffer while reading register
           (put-text-property 0 1 'face 'minibuffer-prompt string)
           (put-text-property 0 1 'cursor t string)
           (overlay-put overlay 'after-string string)
           (list (or evil-this-register (read-char))))
       (delete-overlay overlay))))
  (let ((filename (with-current-buffer helm-current-buffer 
                    (evil-get-register register t))))
    (insert filename)))

(use-package ag :ensure t)

(use-package aggressive-indent :ensure t)

(use-package cl-format :ensure t)

(use-package css-eldoc :ensure t)

(use-package csv-mode :ensure t)

(use-package eldoc-eval :ensure t)

(use-package helm :ensure t :config
  (require 'helm-config)
  (helm-mode)
  (global-set-key
   (kbd "M-x")
   'helm-M-x)
  (global-set-key
   (kbd "C-x C-f")
   'helm-find-files)
  (define-key evil-normal-state-map " f" 'helm-projectile)
  (define-key evil-normal-state-map " j" 'helm-buffers-list)
  (define-key evil-normal-state-map " s" 'helm-occur)
  (define-key evil-normal-state-map " S" 'helm-projectile-rg)
  (define-key helm-map
    (kbd "C-r")
    'fwoar--paste-from-register-mru-buffer)
  (define-key helm-map
    (kbd "<right>")
    'helm-execute-persistent-action)
  (define-key helm-map
    (kbd "<left>")
    'helm-find-files-up-one-level))

(use-package helm-ag :ensure t)

(use-package helm-ag-r :ensure t)

(use-package helm-rg :ensure t)

(use-package helm-cider :ensure t)

(use-package helm-css-scss :ensure t)

(use-package helm-ls-git :ensure t)

(use-package helm-projectile :ensure t)

(use-package helm-projectile :ensure t)

(use-package highlight-parentheses :ensure t :config
  (global-highlight-parentheses-mode 1))



(use-package magit :ensure t
  :config
  (evil-define-key 'normal magit-file-mode-map " a" 'magit)
  ;; TODO: figure this out with transients
  ;;(magit-define-popup-action 'magit-dispatch-popup ?j "Browse remote" 'browse-at-remote)
  'magit-dispatch)


(defvar *fwoar-git-repos*
  (file-name-as-directory
   (expand-file-name (car (file-expand-wildcards "~/git*_repos"))
                     "~")))

(defun fwoar-git-repo (name remote)
  (let ((dir-name (file-name-as-directory (expand-file-name name *fwoar-git-repos*))))
    (unless (file-exists-p dir-name)
      (magit-run-git-with-input "clone" remote dir-name))
    dir-name))

(defvar *dotfiles-repo*
  (fwoar-git-repo "dotfiles" "git@git.fiddlerwoaroof.com:dotfiles.git"))

;; slime depends on fwoar-git-repo
(load-package-configuration 'slime)
(global-company-mode 1)



(use-package markdown-mode :ensure t)

(use-package project-explorer :ensure t)

(use-package rainbow-delimiters :ensure t)

(use-package ripgrep :ensure t)

(use-package projectile-ripgrep :ensure t)

(use-package scss-mode :ensure t)

(use-package smartparens :ensure t :ensure t :config
  (sp-pair "${" "}")
  (sp-with-modes sp--lisp-modes
    (sp-local-pair "'" nil :actions nil)
    (sp-local-pair "`" nil :actions nil))
  (add-hook 'smartparens-enabled-hook 'evil-smartparens-mode))

(use-package web-mode :ensure t)

(use-package yaml-mode :ensure t)


(use-package editorconfig
  :ensure t
  :config (editorconfig-mode 1))

(defun fwoar--activate-treemacs ()
  (interactive)
  (if (treemacs-is-treemacs-window-selected?)
      (delete-window)
    (treemacs-select-window)))

(use-package treemacs
  :ensure t
  :config
  (setq treemacs-is-never-other-window t)
  (global-set-key (kbd "s-e") 'fwoar--activate-treemacs))

(use-package treemacs-evil
  :after treemacs evil
  :ensure t)

(use-package treemacs-projectile
  :after treemacs projectile
  :ensure t)

(use-package treemacs-icons-dired
  :after treemacs dired
  :ensure t
  :config (treemacs-icons-dired-mode))

(use-package treemacs-magit
  :after treemacs magit
  :ensure t)

(progn ;; emacs-lisp stuff
  (modify-syntax-entry ?- "w" emacs-lisp-mode-syntax-table)
  (modify-syntax-entry ?_ "w" emacs-lisp-mode-syntax-table)

  (put 'narrow-to-page 'disabled nil)
  )

;;)


(global-set-key (kbd "s-v") 'yank)

(setq custom-file "~/.emacs.d/custom.el")
(load-file custom-file)


(defun edit-init-el ()
  (interactive)
  (let ((default-directory *dotfiles-repo*))
    (helm-projectile-find-file)))

(setq gc-cons-threshold (* 100 1024))

(unless fwoar.is-ordinary
  (setq with-editor-emacsclient-executable "/usr/local/bin/emacsclient")
  (require 'cjpad)
  (find-file "~/org/notes.org"))

(put 'narrow-to-region
     'disabled
     nil)

(global-set-key (kbd "C-x C-b")
                'ibuffer)

(setq org-agenda-files '("~/org/notes.org"))

(defvar url-pattern (car (read-sexps-in-file "~/.pastebin-name")))
(defun pastebin-buffer ()
  (interactive)
  (let* ((extension (file-name-extension (elt (split-string (buffer-name) "<") 0)))
         (htmlized-buffer (htmlize-buffer)))
    (with-current-buffer htmlized-buffer
      (let ((result-name-hash (sha1 (current-buffer))))
        (write-file (format url-pattern result-name-hash extension))
        (message "Wrote file to: %s.%s.html" result-name-hash extension)
        (browse-url (format "https://fwoar.co/pastebin/%s.%s.html" result-name-hash extension))))))

(defun delete-mru-window ()
  (interactive)
  (delete-window
   (get-mru-window nil nil t)))

(defvar passwords ())
(defslimefun get-passwd (id prompt)
  (let ((val (assoc id passwords)))
    (cdr
     (if val val
       (car (push (cons id (read-passwd prompt))
                  passwords))))))

(add-to-list 'browse-url-filename-alist
             '("/Users/\\([^/]+\\)/\\(Sites\\|public_html\\)\\(/.*\\)" . "https://localhost/~\\1\\3"))

(progn ;; narrowing
  (define-key global-map "\C-c]" "\C-u1\C-xnp")
  (define-key global-map "\C-c[" "\C-u-1\C-xnp\M-<"))


(defun fwoar/zenburn-css ()
  (interactive)
  (mapcar (lambda (desc)
            (destructuring-bind (name . value) desc
              (cl-format (current-buffer)
                         "--~a: ~a;~%"
                         (s-replace "+" "-plus-" name)
                         value)))
          fwoar-zenburn-default-colors-alist))

(defun fwoar/camel-kebab (string)
  (let ((case-fold-search nil))
    (downcase
     (format "%c%s"
             (elt string 0)
             (or (when (> (length string) 1)
                   (s-replace-regexp "[A-Z]"
                                     "-\\&"
                                     string nil nil nil 1))
                 string)))))

(defun fwoar/cc-camel-kebab (start end)
  (interactive "*r")
  (let ((target (buffer-substring start end)))
    (save-excursion
      (delete-region start end)
      (insert (fwoar/camel-kebab target)))))

(defun fwoar--find-package-json ()
  (expand-file-name
   (locate-dominating-file default-directory
                           (lambda (n)
                             (directory-files n nil "^package.json$")))))

(defun find-package-json (default-directory)
  (interactive "D")
  (message "pakcage json: %s"(fwoar--find-package-json))
  (find-file (concat (fwoar--find-package-json)
                     "/package.json")))

(cl-defmethod fwoar--find-system (&context (major-mode (derived-mode js-mode)))
  (find-package-json default-directory))

(use-package org-brain :ensure t
  :init
  (setq org-brain-path "~/org-brain/")

  :config
  (eval-after-load 'evil
    '(evil-set-initial-state 'org-brain-visualize-mode 'emacs))

  (push '("b" "Brain" plain (function org-brain-goto-end)
          "* %i%?" :empty-lines 1)
        org-capture-templates)

  (setq org-id-track-globally t
        org-id-locations-file "~/.emacs.d/.org-id-locations"
        org-brain-visualize-default-choices 'all
        org-brain-title-max-length 12))

(setq diary-file (expand-file-name "~/bucket/diary"))