diff --git a/init.el b/init.el index 6005111c3..03243c317 100644 --- a/init.el +++ b/init.el @@ -48,40 +48,53 @@ (load (concat user-emacs-directory "init-load-path.el")) (mapc 'require - '()) - ;; (;; Settings for specific modes or tools - ;; init-cc ; c/c++/obj-c madness - ;; ;; init-cscope - ;; ;; init-csharp ; unity, mono and xamarin - ;; init-data ; dbs 'n data formats - ;; ;; init-eshell - ;; ;; init-go - ;; init-java ; the poster child for carpal tunnel syndome - ;; init-js ; alert("not java, javascript!") - ;; init-lisp ; elisp, clisp and clojure - ;; init-lua ; one-based indices? one-based indices. - ;; init-org ; for fearless [organized] leader - ;; init-php ; making php less painful to work with - ;; init-python ; beautiful is better than ugly - ;; init-regex ; /^[^\s](meaning)[^\n]*/ - ;; init-ruby ; <3 - ;; init-scss ; @include magic; - ;; init-sh ; #!/bin/bash_your_head_in - ;; ;; init-sonicpi ; the funk soul brotha - ;; ;; init-swift ; yay, emoji variabless! - ;; init-text ; i got nothing... - ;; ;; init-rust - ;; ;; init-r ; for science! - ;; init-vim ; the confessional - ;; init-web ; for the 2.0'er + `(;; benchmark ; records load times in `require-times'; see `list-times' + core ; core/core.el - ;; bindings - ;; commands - ;; ) -;; ) + ,(cond (IS-MAC 'core-os-osx) + (IS-LINUX 'core-os-linux) + (IS-WINDOWS 'core-os-win32)) -(require 'local nil t) -(message ">>> Loaded in %s" (emacs-init-time)) + core-ui ; draw me like one of your French editors + core-evil ; come to the dark side, we have cookies + core-editor ; filling the editor-shaped hole in the emacs OS + core-company ; for the lazy typist + core-yasnippet ; for the lazier typist + core-auto-insert ; for the laziest typist + core-flycheck ; remember that semicolon you forgot? + core-project ; whose project am I in? + core-vcs ; version control is a programmer's best friend + core-helm ; a search engine for life and love + core-quickrun ; run code, run. + core-workgroups ; cure Emacs alzheimers + + module-cc ; c/c++/obj-c madness + module-csharp ; unity, mono and xamarin + module-data ; dbs 'n data formats + module-eshell ; eshell + module-go + module-java ; the poster child for carpal tunnel syndome + module-js ; alert("not java, javascript!") + module-elisp ; + module-lua ; one-based indices? one-based indices. + module-lb6 ; LaunchBar 6 development + module-org ; for fearless [organized] leader + module-php ; making php less painful to work with + module-python ; beautiful is better than ugly + module-regex ; /^[^\s](meaning)[^\n]*/ + module-ruby ; <3 + module-sass ; @include magic; + module-sonicpi ; the funk soul brotha + module-swift ; yay, emoji variabless! + module-markdown ; markdown + ;; module-rust + ;; module-r ; for science! + module-vim ; the confessional + module-web ; for the 2.0'er + + my-bindings + my-commands + )) (defun display-startup-echo-area-message () (message ">>> Loaded in %s" (emacs-init-time))) diff --git a/modules/lib/defuns-cc.el b/modules/lib/defuns-cc.el new file mode 100644 index 000000000..a29ce71cd --- /dev/null +++ b/modules/lib/defuns-cc.el @@ -0,0 +1,79 @@ +;;; defuns-cc.el --- for module-cc.el + +(defun narf--c-lineup-inclass (langelem) + (let ((inclass (assoc 'inclass c-syntactic-context))) + (save-excursion + (goto-char (c-langelem-pos inclass)) + (if (or (looking-at "struct") + (looking-at "typedef struct")) + '+ + '++)))) + +;;;###autoload +(defun narf|init-c/c++-settings () + (c-toggle-electric-state -1) + (c-toggle-auto-newline -1) + (c-set-offset 'substatement-open '0) ; brackets should be at same indentation level as the statements they open + (c-set-offset 'inline-open '+) + (c-set-offset 'block-open '+) + (c-set-offset 'brace-list-open '+) ; all "opens" should be indented by the c-indent-level + (c-set-offset 'case-label '+) ; indent case labels by c-indent-level, too + (c-set-offset 'access-label '-) + (c-set-offset 'inclass 'narf--c-lineup-inclass) + ;; DEL mapping interferes with smartparens and my custom DEL binding + (define-key c-mode-map (kbd "DEL") nil)) + +;;;###autoload +(defun narf*c-lineup-arglist () + "Improve indentation of continued C++11 lambda function opened as argument." + (setq ad-return-value + (if (and (equal major-mode 'c++-mode) + (ignore-errors + (save-excursion + (goto-char (c-langelem-pos langelem)) + ;; Detect "[...](" or "[...]{". preceded by "," or "(", + ;; and with unclosed brace. + (looking-at ".*[(,][ \t]*\\[[^]]*\\][ \t]*[({][^}]*$")))) + 0 ; no additional indent + ad-do-it))) + +;;;###autoload +(defun narf|init-c++-C11-highlights () + ;; We could place some regexes into `c-mode-common-hook', but + ;; note that their evaluation order matters. + (font-lock-add-keywords + nil '(;; complete some fundamental keywords + ("\\<\\(void\\|unsigned\\|signed\\|char\\|short\\|bool\\|int\\|long\\|float\\|double\\)\\>" . font-lock-keyword-face) + ;; namespace names and tags - these are rendered as constants by cc-mode + ("\\<\\(\\w+::\\)" . font-lock-function-name-face) + ;; new C++11 keywords + ("\\<\\(alignof\\|alignas\\|constexpr\\|decltype\\|noexcept\\|nullptr\\|static_assert\\|thread_local\\|override\\|final\\)\\>" . font-lock-keyword-face) + ("\\<\\(char16_t\\|char32_t\\)\\>" . font-lock-keyword-face) + ;; PREPROCESSOR_CONSTANT, PREPROCESSORCONSTANT + ("\\<[A-Z]*_[A-Z_]+\\>" . font-lock-constant-face) + ("\\<[A-Z]\\{3,\\}\\>" . font-lock-constant-face) + ;; hexadecimal numbers + ("\\<0[xX][0-9A-Fa-f]+\\>" . font-lock-constant-face) + ;; integer/float/scientific numbers + ("\\<[\\-+]*[0-9]*\\.?[0-9]+\\([ulUL]+\\|[eE][\\-+]?[0-9]+\\)?\\>" . font-lock-constant-face) + ;; c++11 string literals + ;; L"wide string" + ;; L"wide string with UNICODE codepoint: \u2018" + ;; u8"UTF-8 string", u"UTF-16 string", U"UTF-32 string" + ("\\<\\([LuU8]+\\)\".*?\"" 1 font-lock-keyword-face) + ;; R"(user-defined literal)" + ;; R"( a "quot'd" string )" + ;; R"delimiter(The String Data" )delimiter" + ;; R"delimiter((a-z))delimiter" is equivalent to "(a-z)" + ("\\(\\<[uU8]*R\"[^\\s-\\\\()]\\{0,16\\}(\\)" 1 font-lock-keyword-face t) ; start delimiter + ( "\\<[uU8]*R\"[^\\s-\\\\()]\\{0,16\\}(\\(.*?\\))[^\\s-\\\\()]\\{0,16\\}\"" 1 font-lock-string-face t) ; actual string + ( "\\<[uU8]*R\"[^\\s-\\\\()]\\{0,16\\}(.*?\\()[^\\s-\\\\()]\\{0,16\\}\"\\)" 1 font-lock-keyword-face t) ; end delimiter + + ;; user-defined types (rather project-specific) + ("\\<[A-Za-z_]+[A-Za-z_0-9]*_\\(type\\|ptr\\)\\>" . font-lock-type-face) + ("\\<\\(xstring\\|xchar\\)\\>" . font-lock-type-face) + ) t)) + + +(provide 'defuns-cc) +;;; defuns-cc.el ends here diff --git a/modules/lib/defuns-elisp.el b/modules/lib/defuns-elisp.el new file mode 100644 index 000000000..7db422605 --- /dev/null +++ b/modules/lib/defuns-elisp.el @@ -0,0 +1,16 @@ +;;; defuns-elisp.el + +;;;###autoload +(defun narf/elisp-find-function-at-pt () + (interactive) + (let ((func (function-called-at-point))) + (if func (find-function func)))) + +;;;###autoload +(defun narf/elisp-find-function-at-pt-other-window () + (interactive) + (let ((func (function-called-at-point))) + (if func (find-function-other-window func)))) + +(provide 'defuns-elisp) +;;; defuns-elisp.el ends here diff --git a/modules/lib/defuns-eshell.el b/modules/lib/defuns-eshell.el new file mode 100644 index 000000000..468b5ed31 --- /dev/null +++ b/modules/lib/defuns-eshell.el @@ -0,0 +1,61 @@ +;;; defuns-eshell.el --- + +(defun narf--eshell-in-prompt-p (&optional offset) + (>= (- (point) (or offset 0)) (save-excursion (eshell-bol) (point)))) + +(defun narf--eshell-current-git-branch () + (let ((branch (car (loop for match in (split-string (shell-command-to-string "git branch") "\n") + when (string-match "^\*" match) + collect match)))) + (if (not (eq branch nil)) + (concat " [" (substring branch 2) "]") + ""))) + +;;;###autoload +(defun narf/eshell-prompt () + (concat (propertize (abbreviate-file-name (eshell/pwd)) 'face 'eshell-prompt) + (propertize (narf--eshell-current-git-branch) 'face 'font-lock-function-name-face) + (propertize " $ " 'face 'font-lock-constant-face))) + +;;;###autoload +(defun narf/eshell-evil-append () + (interactive) + (goto-char (point-max)) + (call-interactively 'evil-append)) + +;;;###autoload +(defun narf/eshell-evil-append-maybe () + (interactive) + (if (narf--eshell-in-prompt-p) + (call-interactively 'evil-insert) + (narf/eshell-append))) + +;;;###autoload +(defun narf/eshell-evil-prepend () + (interactive) + (eshell-bol) + (call-interactively 'evil-insert)) + +;;;###autoload +(defun narf/eshell-evil-prepend-maybe () + (interactive) + (if (narf--eshell-in-prompt-p) + (call-interactively 'evil-insert) + (narf/eshell-prepend))) + +;;;###autoload +(defun narf/eshell-evil-replace-maybe () + (interactive) + (if (narf--eshell-in-prompt-p) + (call-interactively 'evil-replace) + (user-error "Cannot edit read-only region"))) + +;;;###autoload +(defun narf/eshell-evil-replace-state-maybe () + (interactive) + (if (narf--eshell-in-prompt-p) + (call-interactively 'evil-replace-state) + (user-error "Cannot edit read-only region"))) + +(provide 'defuns-eshell) +;;; defuns-eshell.el ends here diff --git a/modules/lib/defuns-java.el b/modules/lib/defuns-java.el new file mode 100644 index 000000000..a634b7d6e --- /dev/null +++ b/modules/lib/defuns-java.el @@ -0,0 +1,48 @@ +;;; defuns-java.el --- + +;;;###autoload +(defun narf/java-project-package () + (if (eq major-mode 'java-mode) + (s-chop-suffix "." (s-replace "/" "." (f-dirname (f-relative (buffer-file-name) + (concat (narf/project-root) "/src/"))))) + "")) + +;;;###autoload +(defun narf/java-class-name () + (if (eq major-mode 'java-mode) + (f-no-ext (f-base (buffer-file-name))) + "")) + +;; yasnippet defuns +;;;###autoload +(defun narf/java-android-mode-is-layout-file () + (and android-mode + (eq major-mode 'nxml-mode) + (string-equal (file-name-base (directory-file-name default-directory)) "layout"))) + +;;;###autoload +(defun narf/java-android-mode-in-tags (&rest tags) + (-contains? tags (android-mode-tag-name))) + +;;;###autoload +(defun narf/java-android-mode-tag-name () + (save-excursion + (let (beg end) + (nxml-backward-up-element) + (evil-forward-word-begin) + (setq beg (point)) + (evil-forward-WORD-end) + (setq end (1+ (point))) + (buffer-substring-no-properties beg end)))) + +;;;###autoload +(defun narf|android-mode-enable-maybe () + (let ((root (narf/project-root))) + (when (or (narf/project-has-files "local.properties" root) + (narf/project-has-files "AndroidManifest.xml" root) + (narf/project-has-files "src/main/AndroidManifest.xml" root)) + (android-mode +1) + (narf/set-build-command "./gradlew %s" "build.gradle")))) + +(provide 'defuns-java) +;;; defuns-java.el ends here diff --git a/modules/lib/defuns-markdown.el b/modules/lib/defuns-markdown.el new file mode 100644 index 000000000..86655831b --- /dev/null +++ b/modules/lib/defuns-markdown.el @@ -0,0 +1,25 @@ +;;; defuns-markdown.el --- for module-markdown.el + +;; Implement strike-through formatting +(defvar narf--markdown-regex-del + "\\(^\\|[^\\]\\)\\(\\(~\\{2\\}\\)\\([^ \n \\]\\|[^ \n ]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(\\3\\)\\)") + +;;;###autoload +(defun narf/markdown-insert-del () + "Surround region in github strike-through delimiters." + (interactive) + (let ((delim "~~")) + (if (markdown-use-region-p) + ;; Active region + (let ((bounds (markdown-unwrap-things-in-region + (region-beginning) (region-end) + narf--markdown-regex-del 2 4))) + (markdown-wrap-or-insert delim delim nil (car bounds) (cdr bounds))) + ;; Bold markup removal, bold word at point, or empty markup insertion + (if (thing-at-point-looking-at narf--markdown-regex-del) + (markdown-unwrap-thing-at-point nil 2 4) + (markdown-wrap-or-insert delim delim 'word nil nil))))) + + +(provide 'defuns-markdown) +;;; defuns-markdown.el ends here diff --git a/modules/lib/defuns-org.el b/modules/lib/defuns-org.el new file mode 100644 index 000000000..512b4515b --- /dev/null +++ b/modules/lib/defuns-org.el @@ -0,0 +1,124 @@ +;;; defuns-org.el + +;;;###autoload +(defun narf/org-cycle-hide-drawers (state) + "Re-hide all drawers after a visibility state change. Hides properties permanently." + (when (and (derived-mode-p 'org-mode) + (not (memq state '(overview folded contents)))) + (save-excursion + (let* ((globalp (memq state '(contents all))) + (beg (if globalp (point-min) (point))) + (end (if globalp (point-max) + (if (eq state 'children) + (save-excursion (outline-next-heading) (point)) + (org-end-of-subtree t))))) + (goto-char beg) + (while (re-search-forward org-drawer-regexp end t) + (save-excursion + (beginning-of-line 1) + (backward-char 1) + (let ((b (point))) + (if (re-search-forward + "^[ \t]*:END:" + (save-excursion (outline-next-heading) (point)) t) + (outline-flag-region b (point-at-eol) t) + (user-error ":END: line missing at position %s" b))))))))) + +(defun narf--org-in-list-p () + (and (save-excursion (search-backward-regexp "^ *\\([0-9]+[\.)]\\|[-*+]\\) " + (line-beginning-position) t)) + (org-in-item-p))) + +;;;###autoload +(defun narf/project-org-filename (cat) + (interactive (list (completing-read "Choose category:" + (mapcar 'f-filename (f-directories org-project-directory))))) + (expand-file-name (concat (file-name-nondirectory (directory-file-name (narf/project-root))) ".org") + (expand-file-name cat org-project-directory))) + +;;;###autoload +(defun narf/org-insert-item-after () + "Inserts a new heading or item, depending on the context." + (interactive) + (org-end-of-line) + (cond ((org-at-item-checkbox-p) + (org-insert-heading) + (insert "[ ] ")) + ((narf--org-in-list-p) + (org-insert-heading)) + ((org-on-heading-p) + (org-insert-heading-after-current)) + (t + (org-insert-heading-after-current) + (delete-char 1))) + (evil-insert-state)) + +;; TODO Check if this and -forward can be combined +;;;###autoload +(defun narf/org-insert-item-before () + "Inserts a new heading or item, depending on the context." + (interactive) + (evil-first-non-blank) + (cond ((org-at-item-checkbox-p) + (org-insert-heading) + (insert "[ ] ")) + ((narf--org-in-list-p) + (org-insert-heading)) + (t (org-insert-heading))) + (evil-insert-state)) + +;;;###autoload +(defun narf/org-toggle-checkbox () + (interactive) + (save-excursion + (org-end-of-line) + (cond ((org-in-item-p) + (if (search-backward-regexp "\\[[ +-]\\]" (line-beginning-position) t) + (delete-char 4) + (org-beginning-of-line))) + (t (org-insert-heading))) + (insert "[ ] "))) + +;; Formatting shortcuts +;;;###autoload +(defun narf/org-surround (delim) + (insert delim) (save-excursion (insert delim))) + +;;;###autoload (autoload 'narf:org-insert-image-url "defuns-org" nil t) +(evil-define-command narf:org-insert-image-url (&optional image-url) + :repeat nil + (interactive "") + (unless image-url + (user-error "You must specify an image URL to insert")) + (let ((dest (f-join org-directory "images/" (concat (format-time-string "%Y%m%d-") (f-filename image-url))))) + (shell-command (format "wget '%s' -O '%s'" image-url dest)) + (insert (format "<%s>" (f-relative dest (f-dirname (buffer-file-name))))) + (indent-according-to-mode))) + +;;;###autoload (autoload 'narf:org-insert-image "defuns-org" nil t) +(evil-define-command narf:org-insert-image (&optional filename bang) + :repeat nil + (interactive "") + (if bang + (narf:org-insert-image-url filename) + (unless filename + (user-error "You must specify a file to attach")) + (unless (file-exists-p filename) + (user-error "File %s does not exist" filename)) + (let ((dest (f-join org-directory "images/" (concat (format-time-string "%Y%m%d-") (f-filename filename))))) + (when (file-exists-p dest) + (user-error "File %s already exists at destination!")) + (copy-file filename dest) + (insert (format "" (f-relative dest (f-dirname (buffer-file-name))))) + (indent-according-to-mode)))) + +;;;###autoload (autoload 'narf:org-search-files-or-headers "defuns-org" nil t) +(evil-define-command narf:org-search-files-or-headers (&optional bang) + (interactive "") + (require 'org) + (if bang + (ido-find-file-in-dir org-directory) + (call-interactively 'helm-org-agenda-files-headings))) + +(provide 'defuns-org) +;;; defuns-org.el ends here diff --git a/modules/lib/defuns-python.el b/modules/lib/defuns-python.el new file mode 100644 index 000000000..9db69cfaf --- /dev/null +++ b/modules/lib/defuns-python.el @@ -0,0 +1,11 @@ +;;; defuns-python.el + +;;;###autoload +(defun narf*anaconda-mode-doc-buffer () + "Delete the window on escape or C-g." + (with-current-buffer (get-buffer "*anaconda-doc*") + (local-set-key [escape] 'anaconda-nav-quit) + (local-set-key [?\C-g] 'anaconda-nav-quit))) + +(provide 'defuns-python) +;;; defuns-python.el ends here diff --git a/modules/lib/defuns-regex.el b/modules/lib/defuns-regex.el new file mode 100644 index 000000000..1efa1edbf --- /dev/null +++ b/modules/lib/defuns-regex.el @@ -0,0 +1,40 @@ +;;; defuns-regex.el + +;;;###autoload +(defun narf|reb-cleanup () + (replace-regexp "^[ \n]*" "" nil (point-min) (point-max)) + (text-scale-set 1.5) + (goto-char 2)) + +;;;###autoload (autoload 'narf:regex "defuns-regex" nil t) +(evil-define-operator narf:regex (beg end type &optional regexstr bang) + "Either a) converts selected (or entered-in) pcre regex into elisp +regex, OR b) opens up re-builder." + :move-point nil + :type inclusive + :repeat nil + (interactive "") + (if (reb-mode-buffer-p) + (if regexstr + (let ((regexstr (s-trim (buffer-string)))) + (if bang + (rxt-explain-pcre regexstr) + (rxt-pcre-to-elisp (s-trim (buffer-string))))) + (erase-buffer) + (insert (concat "/" regexstr "/"))) + (cond ((and beg end (/= beg (1- end))) ; Convert selection from pcre regex to elisp + (let ((regexstr (buffer-substring-no-properties beg end))) + (if bang + (rxt-explain-pcre (concat "/" regexstr "/")) + (delete-region beg end) + (insert (rxt-pcre-to-elisp regexstr))))) + (regexstr ; Convert input regex into elisp regex + (let ((newregex (rxt-pcre-to-elisp regexstr))) + (when bang + (setq newregex (s-replace "\\" "\\\\" newregex))) + (kill-new newregex) + (message "Copied regex to kill ring: %s" newregex))) + (t (re-builder))))) + +(provide 'defuns-regex) +;;; defuns-regex.el ends here diff --git a/modules/lib/defuns-ruby.el b/modules/lib/defuns-ruby.el new file mode 100644 index 000000000..6b2496cba --- /dev/null +++ b/modules/lib/defuns-ruby.el @@ -0,0 +1,25 @@ +;;; defuns-ruby.el + +;;;###autoload +(defun narf|enable-robe-maybe () + (let ((file (buffer-file-name))) + ;; Don't run in gemfiles, capfiles or vagrantfiles + (unless (or (string-equal (f-filename file) "Gemfile") + (string-equal (f-filename file) "Capfile") + (string-equal (f-filename file) "Vagrantfile") + (f-ext? file "org")) ;; or org-mode + (robe-mode 1) + (narf|ruby-load-file file)))) + +;;;###autoload +(defun narf|ruby-load-file (&optional file) + (let ((file (or file buffer-file-name))) + (when (and (eq major-mode 'enh-ruby-mode) + (featurep 'robe) + (not (string= (f-base file) "Gemfile")) + (file-exists-p buffer-file-name)) + (unless robe-running (robe-start 1)) + (when robe-running (ruby-load-file file))))) + +(provide 'defuns-ruby) +;;; defuns-ruby.el ends here diff --git a/modules/module-cc.el b/modules/module-cc.el new file mode 100644 index 000000000..c8a282fa9 --- /dev/null +++ b/modules/module-cc.el @@ -0,0 +1,93 @@ +;;; module-cc.el + +(use-package cmake-mode + :mode "CMakeLists\\.txt$" + :config + (after! company + (require 'company-cmake) + (add-company-backend! cmake-mode (cmake yasnippet)))) + +(use-package glsl-mode + :mode (("\\.glsl\\'" . glsl-mode) + ("\\.vert\\'" . glsl-mode) + ("\\.frag\\'" . glsl-mode) + ("\\.geom\\'" . glsl-mode))) + +(use-package cc-mode + :defines (c-syntactic-context) + :functions (c-toggle-electric-state c-toggle-auto-newline + c-skip-comments-and-strings c-forward-sws c-end-of-macro + c-font-lock-invalid-string csharp-log c-font-lock-declarators + c-get-lang-constant c-forward-keyword-clause + c-fontify-recorded-types-and-refs c-forward-type imenu--split + c-backward-sws c-determine-limit c-beginning-of-decl-1) + :commands (c-mode c++-mode objc-mode java-mode) + :init + (associate! c++-mode :match "\\.h$") + (associate! objc-mode :match "\\.mm$") + :config + (setq c-basic-offset 4 + c-tab-always-indent nil + c-electric-flag nil) + + (progn ; C/C++ Settings + (when IS-MAC + (after! flycheck + (setq flycheck-clang-language-standard "c++11" + flycheck-clang-standard-library "libc++" + flycheck-c/c++-clang-executable "clang++" + flycheck-clang-include-path '("/usr/local/include")))) + + (after! company + ;; TODO Clang is *really* slow in larger projects, maybe replace it with + ;; irony-mode or ycmd? + (add-company-backend! c-mode (c-headers clang)) + (add-company-backend! c++-mode (c-headers clang)) + (add-company-backend! objc-mode (c-headers xcode))) + + (add-hook! c-mode 'narf|init-c/c++-settings) + (add-hook! c++-mode 'narf|init-c/c++-settings) + + ;; C++11 syntax support (until cc-mode is updated) + (require 'font-lock) + (defun --copy-face (new-face face) + "Define NEW-FACE from existing FACE." + (copy-face face new-face) + (eval `(defvar ,new-face nil)) + (set new-face new-face)) + ;; labels, case, public, private, protected, namespace-tags + (--copy-face 'font-lock-label-face 'font-lock-keyword-face) + ;; comment markups such as Javadoc-tags + (--copy-face 'font-lock-doc-markup-face 'font-lock-doc-face) + ;; comment markups + (--copy-face 'font-lock-doc-string-face 'font-lock-comment-face) + (setq font-lock-maximum-decoration t) + (add-hook! c++-mode 'narf|init-c++-C11-highlights) + + ;; Fix enum and C++11 lambda indentation + (advice-add 'c-lineup-arglist :around 'narf*c-lineup-arglist) + ;; (defadvice c-lineup-arglist (around c-lineup-arglist-indent-fix activate) + ;; "Improve indentation of continued C++11 lambda function opened as argument." + ;; (setq ad-return-value + ;; (if (and (equal major-mode 'c++-mode) + ;; (ignore-errors + ;; (save-excursion + ;; (goto-char (c-langelem-pos langelem)) + ;; ;; Detect "[...](" or "[...]{". preceded by "," or "(", + ;; ;; and with unclosed brace. + ;; (looking-at ".*[(,][ \t]*\\[[^]]*\\][ \t]*[({][^}]*$")))) + ;; 0 ; no additional indent + ;; ad-do-it))) + ) + + (progn ; Obj-C + (add-to-list 'magic-mode-alist + `(,(lambda () + (and (string= (file-name-extension buffer-file-name) "h") + (re-search-forward "@\\" + magic-mode-regexp-match-limit t))) + . objc-mode)) + (after! flycheck (add-hook! objc-mode (require 'flycheck-objc))))) + +(provide 'module-cc) +;;; module-cc.el ends here diff --git a/modules/module-csharp.el b/modules/module-csharp.el new file mode 100644 index 000000000..6a39c3eff --- /dev/null +++ b/modules/module-csharp.el @@ -0,0 +1,25 @@ +;;; module-csharp.el + +(use-package csharp-mode + :functions (csharp-log) + :mode "\\.cs$" + :init (add-hook! csharp-mode 'flycheck-mode)) + +(use-package omnisharp + :after csharp-mode + :config + (setq omnisharp-server-executable-path + "~/Dropbox/projects/lib/Omnisharp/server/OmniSharp/bin/Debug/OmniSharp.exe") + + (bind! :map omnisharp-mode-map + :n "gd" 'omnisharp-go-to-definition) + + (after! company + (add-company-backend! csharp-mode (omnisharp)) + (add-hook! csharp-mode 'turn-on-eldoc-mode))) + +;; unity shaders +(use-package shaderlab-mode :mode "\\.shader$") + +(provide 'module-csharp) +;;; module-csharp.el ends here diff --git a/modules/module-data.el b/modules/module-data.el new file mode 100644 index 000000000..ff0c6e9eb --- /dev/null +++ b/modules/module-data.el @@ -0,0 +1,14 @@ +;;; module-data.el --- dbs 'n data formats + +(use-package yaml-mode + :mode "\\.ya?ml$" + :init (add-hook! yaml-mode 'narf|enable-tab-width-2)) + +(use-package json-mode + :mode (("\\.json$" . json-mode) + ("\\.jshintrc$" . json-mode))) + +;; TODO: Db client + +(provide 'module-data) +;;; module-data.el ends here diff --git a/modules/module-elisp.el b/modules/module-elisp.el new file mode 100644 index 000000000..660cc4df0 --- /dev/null +++ b/modules/module-elisp.el @@ -0,0 +1,16 @@ +;;; module-elisp --- all things emacs lisp +;; see lib/elisp-defuns.el + +(add-hook! emacs-lisp-mode 'turn-on-eldoc-mode) + +;; [pedantry intensifies] +(defadvice emacs-lisp-mode (after emacs-lisp-mode-rename-modeline activate) + (setq mode-name "Elisp")) + +;; Real go-to-definition for elisp +(bind! :map emacs-lisp-mode-map + :m "gd" 'narf/elisp-find-function-at-pt + :m "gD" 'narf/elisp-find-function-at-pt-other-window) + +(provide 'module-elisp) +;;; module-elisp.el ends here diff --git a/modules/module-eshell.el b/modules/module-eshell.el new file mode 100644 index 000000000..159dfd4e3 --- /dev/null +++ b/modules/module-eshell.el @@ -0,0 +1,39 @@ +;;; module-eshell.el + +(use-package eshell + :defer t + :init + (evil-set-initial-state 'eshell-mode 'normal) + (add-popwin-rule! "*eshell*" :position left :width 80 :stick t :dedicated t) + + (setq eshell-directory-name (! (concat narf-temp-dir "eshell")) + eshell-scroll-to-bottom-on-input 'all + eshell-buffer-shorthand t + + ;; em-glob + eshell-glob-case-insensitive t + eshell-error-if-no-glob t + + ;; em-alias + eshell-aliases-file (concat narf-temp-dir ".eshell-aliases")) + + ;; plan 9 smart shell + (require 'em-smart) + (add-to-list 'eshell-modules-list 'eshell-smart) + (setq eshell-where-to-jump 'begin) + (setq eshell-review-quick-commands nil) + (setq eshell-smart-space-goes-to-end t) + + ;; em-prompt + (setq eshell-prompt-function 'narf/eshell-prompt) + + (bind! :map eshell-mode-map + :n "i" 'narf/eshell-evil-prepend-maybe + :n "I" 'narf/eshell-evil-prepend + :n "a" 'narf/eshell-evil-append-maybe + :n "A" 'narf/eshell-evil-append + :n "r" 'narf/eshell-evil-replace-maybe + :n "R" 'narf/eshell-evil-replace-state-maybe)) + +(provide 'module-eshell) +;;; module-eshell.el ends here diff --git a/modules/module-go.el b/modules/module-go.el new file mode 100644 index 000000000..078a680b1 --- /dev/null +++ b/modules/module-go.el @@ -0,0 +1,14 @@ +;;; module-go.el + +(use-package go-mode + :mode "\\.go$" + :interpreter "go" + :config + (bind! :map go-mode-map :n "gd" 'godef-jump) + + (use-package company-go + :config + (add-company-backend! go-mode (go yasnippet)))) + +(provide 'module-go) +;;; module-go.el ends here diff --git a/modules/module-java.el b/modules/module-java.el new file mode 100644 index 000000000..d76aaad50 --- /dev/null +++ b/modules/module-java.el @@ -0,0 +1,43 @@ +;;; module-java.el --- the poster child for carpal tunnel + +(use-package eclim + :functions (eclim--project-dir eclim--project-name) + :commands (eclim-mode global-eclim-mode) + :init + (setq eclim-eclipse-dirs '("/Applications/eclipse") + eclim-executable "/Applications/eclipse/eclim") + (when (file-exists-p eclim-executable) + (add-hook! java-mode 'eclim-mode)) + :config + ;; (use-package eclim-ant) + ;; (use-package eclim-maven) + (require 'eclim-problems) + (require 'eclim-project) + (require 'eclimd) + + (setq help-at-pt-display-when-idle t) + (setq help-at-pt-timer-delay 0.1) + (help-at-pt-set-timer) + + (push "*eclim: problems*" winner-boring-buffers) + + (after! company + (use-package company-emacs-eclim + :functions company-emacs-eclim-setup + :config (company-emacs-eclim-setup))) + + (bind! :map java-mode-map :m "gd" 'eclim-java-find-declaration)) + +(use-package android-mode + :commands android-mode + :init + ;; (after! company-dict (add-to-list 'company-dict-minor-mode-alist 'android-mode)) + (add-hook! (java-mode groovy-mode nxml-mode) 'narf|android-mode-enable-maybe) + (add-hook! android-mode (add-yas-minor-mode! 'android-mode))) + +(use-package groovy-mode + :functions (is-groovy-mode) + :mode "\\.gradle$") + +(provide 'module-java) +;;; module-java.el ends here diff --git a/modules/module-js.el b/modules/module-js.el new file mode 100644 index 000000000..449294985 --- /dev/null +++ b/modules/module-js.el @@ -0,0 +1,45 @@ +;;; module-js.el + +(use-package js2-mode + :mode "\\.js$" + :interpreter "node" + :config + (setq-default + js2-skip-preprocessor-directives t + js2-show-parse-errors nil + js2-global-externs '("module" "require" "buster" "sinon" "assert" + "refute" "setTimeout" "clearTimeout" + "setInterval" "clearInterval" "location" + "__dirname" "console" "JSON" "jQuery" "$" + ;; Launchbar API + "LaunchBar" "File" "Action" "HTTP" "include")) + + (after! web-beautify + (add-hook! js2-mode (setenv "jsbeautify_indent_size" "4")) + (bind! :map js2-mode-map :m "gQ" 'web-beautify-js)) + + (after! emr (require 'js2-refactor)) + + ;; [pedantry intensifies] + (defadvice js2-mode (after js2-mode-rename-modeline activate) + (setq mode-name "JS2"))) + +(use-package tern + :diminish (tern-mode . "tern") + :commands tern-mode + :init (add-hook! js2-mode 'tern-mode) + :config + (after! company + (require 'company-tern) + (add-company-backend! js2-mode (tern)))) + +(use-package unityjs-mode + :mode "/Assets/*.js$" + :config + (add-hook! unityjs-mode 'flycheck-mode) + (add-hook! unityjs-mode + (narf|enable-tab-width-2) + (setq js-indent-level 2))) + +(provide 'module-js) +;;; module-js.el ends here diff --git a/modules/module-lb6.el b/modules/module-lb6.el new file mode 100644 index 000000000..408e579cd --- /dev/null +++ b/modules/module-lb6.el @@ -0,0 +1,13 @@ +;;; module-lb6.el + +(define-minor-mode lb6-mode + "Launchbar development mode." + :init-value nil + :lighter "lb6" + :keymap (make-sparse-keymap) + (add-yas-minor-mode! 'lb6-mode)) + +(associate! lb6-mode :match "\\.lb\\(action\\|ext\\)/.*$") + +(provide 'module-lb6) +;;; module-lb6.el ends here diff --git a/modules/module-lua.el b/modules/module-lua.el new file mode 100644 index 000000000..fe85a84f3 --- /dev/null +++ b/modules/module-lua.el @@ -0,0 +1,27 @@ +;;; module-lua.el --- lua + Love2D + +(use-package lua-mode + :mode "\\.lua$" + :interpreter "lua" + :init + (setq-default lua-indent-level tab-width) + + ;; (after! company-dict + ;; (add-to-list 'company-dict-minor-mode-alist 'love-mode)) + + (add-hook! lua-mode + (narf|enable-tab-width-2) + (setq lua-indent-level 2))) + +(define-minor-mode love-mode + "Buffer local minor mode for Love2D" + :init-value nil + :lighter " <3" + :keymap (make-sparse-keymap) + (add-yas-minor-mode! 'love-mode)) + +(associate! love-mode :files ("main.lua")) +(build-for! love-mode "open -a love.app '%s'" "main.lua") + +(provide 'module-lua) +;;; module-lua.el ends here diff --git a/modules/module-markdown.el b/modules/module-markdown.el new file mode 100644 index 000000000..d03aea31d --- /dev/null +++ b/modules/module-markdown.el @@ -0,0 +1,37 @@ +;;; module-markdown.el +;; see lib/markdown-defuns.el + +(use-package markdown-mode + :mode (("\\.md$" . markdown-mode) + ("/README$" . markdown-mode)) + :functions (markdown-use-region-p + markdown-unwrap-things-in-region + markdown-wrap-or-insert + markdown-unwrap-thing-at-point) + :config + (bind! :map markdown-mode-map + "" nil + "" nil + "" nil + + "M-*" 'markdown-insert-list-item + "M-b" 'markdown-insert-bold + "M-i" 'markdown-insert-italic + "M-`" 'narf/markdown-insert-del + + (:prefix "," ; + :nv "i" 'markdown-insert-image + :nv "l" 'markdown-insert-link + :nv "L" 'markdown-insert-reference-link-dwim + :nv "b" 'markdown-preview) + + ;; TODO: Make context sensitive + :n "[p" 'markdown-promote + :n "]p" 'markdown-demote + + :i "M--" 'markdown-insert-hr)) + +;; TODO: Test previewing capability + +(provide 'module-markdown) +;;; module-markdown.el ends here diff --git a/modules/module-org.el b/modules/module-org.el new file mode 100644 index 000000000..634dc0911 --- /dev/null +++ b/modules/module-org.el @@ -0,0 +1,211 @@ +;;; module-org.el + +(define-minor-mode evil-org-mode + "Evil-mode bindings for org-mode." + :init-value nil + :lighter "!" + :keymap (make-sparse-keymap) ; defines evil-org-mode-map + :group 'evil-org) + +(use-package org + :defines (org-directory) + :functions (org-bookmark-jump-unhide outline-next-heading org-end-of-subtree + outline-flag-region org-remove-inline-images org-display-inline-images + org-at-item-checkbox-p org-toggle-checkbox org-entry-is-todo-p org-todo + org-format-outline-path org-get-outline-path) + :commands (org-capture org-capture-string) + :mode (("\\.org$" . org-mode) + ("\\.opml$" . org-mode)) + :init + (add-hook! org-mode (hl-line-mode -1)) + (add-hook! org-mode '(narf|enable-tab-width-2 + narf|enable-hard-wrap + iimage-mode + org-indent-mode + evil-org-mode)) + (setq org-directory "~/Dropbox/notes/") + :config + (after! org-indent (diminish 'org-indent-mode)) + (after! iimage (diminish 'iimage-mode)) + + (defun narf--org-all-files () + (f-entries org-directory + (lambda (path) + (and (f-ext? path "org") + (not (f-same? path (f-expand "inbox.org" org-directory))))) + t)) + + (setq org-project-directory (! (concat org-directory "projects")) ; not an org var + org-default-notes-file (! (concat org-directory "notes.org")) + org-agenda-files (narf--org-all-files) + org-archive-location (! (concat org-directory "/archive/%s::")) + org-confirm-babel-evaluate nil + org-src-tab-acts-natively t + org-image-actual-width 250 + org-startup-with-inline-images t + org-completion-use-ido t + org-hidden-keywords '(title) + org-special-ctrl-a/e t + org-hide-leading-stars t + org-hierarchical-todo-statistics t + org-checkbox-hierarchical-statistics t + org-tags-column -87 + org-log-done t + org-confirm-elisp-link-function nil + org-startup-folded 'content + org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") + (sequence "DOING(s)" "PENDING(p)") + (sequence "|" "CANCELLED(c)")) + org-mobile-directory "~/Dropbox/Apps/MobileOrg" + org-mobile-inbox-for-pull (! (expand-file-name "mobile.org" org-directory))) + + (setq org-src-fontify-natively t + org-blank-before-new-entry '((heading . auto) (plain-list-item . auto)) + org-export-backends '(ascii html latex md opml)) + + (add-to-list 'org-link-frame-setup '(file . find-file)) + + (setq org-tag-alist '(("@home" . ?h) + ("@daily" . ?d) + ("@invoices" . ?i) + ("@personal" . ?p) + ("@learning" . ?l) + ("@dev" . ?v) + ("@writing" . ?w) + ("@projects" . ?r))) + + (setq org-capture-templates + '(("t" "TODO" entry (file+headline "~/Dropbox/notes/todo.org" "Inbox") "* TODO %? %u\n%i") + ("T" "Project TODO" entry (file+headline (narf/project-org-filename) "Tasks") "** TODO %?\n%i" :prepend t) + ("N" "Project Note" entry (file+headline (narf/project-org-filename) "Notes") "** %u %?\n%i") + ("c" "Changelog" entry (file+datetree (narf/project-org-filename)) "** %<%H:%M>: %? :unsorted:\n%i" :prepend t) + ("n" "Note" entry (file+datetree org-default-notes-file) "** %<%H:%M>: %?\n%i" :prepend t) + ("j" "Journal" entry (file+datetree "~/Dropbox/notes/journal.org") "** %?%^g\nAdded: %U\n%i") + ("a" "Trivia" entry (file "~/Dropbox/notes/trivia.org") "* %u %?\n%i" :prepend t) + ("s" "Writing Scraps" entry (file "~/Dropbox/notes/writing.org") "* %u %?\n%i" :prepend t) + ("v" "Vocab" entry (file "~/Dropbox/notes/vocab.org") "* %?\n%i" :prepend t) + ("e" "Excerpt" entry (file "~/Dropbox/notes/excerpts.org") "* %u %?\n%i" :prepend t))) + + (setq iimage-mode-image-regex-alist + '(("\\(`?file://\\|\\[\\[\\|<\\|`\\)?\\([-+./_0-9a-zA-Z]+\\.\\(GIF\\|JP\\(?:E?G\\)\\|P\\(?:BM\\|GM\\|N[GM]\\|PM\\)\\|SVG\\|TIFF?\\|X\\(?:[BP]M\\)\\|gif\\|jp\\(?:e?g\\)\\|p\\(?:bm\\|gm\\|n[gm]\\|pm\\)\\|svg\\|tiff?\\|x\\(?:[bp]m\\)\\)\\)\\(\\]\\]\\|>\\|'\\)?" . 2) + ("<\\(http://.+\\.\\(GIF\\|JP\\(?:E?G\\)\\|P\\(?:BM\\|GM\\|N[GM]\\|PM\\)\\|SVG\\|TIFF?\\|X\\(?:[BP]M\\)\\|gif\\|jp\\(?:e?g\\)\\|p\\(?:bm\\|gm\\|n[gm]\\|pm\\)\\|svg\\|tiff?\\|x\\(?:[bp]m\\)\\)\\)>" . 1))) + + (org-babel-do-load-languages 'org-babel-load-languages + '((python . t) + (ruby . t) + (sh . t) + (emacs-lisp . t) + (matlab . t) + (latex . t))) + + (advice-add 'evil-force-normal-state :before 'org-remove-occur-highlights) + (advice-add 'org-cycle-hide-drawers :override 'narf/org-cycle-hide-drawers) + + (use-package org-agenda + :config + (setq org-agenda-restore-windows-after-quit t + org-agenda-custom-commands + '(("x" agenda) + ("y" agenda*) + ("w" todo "WAITING") + ("W" todo-tree "WAITING") + ("to" todo) + ("tp" tags "+Projects") + ("tg" tags-todo "+gamedev") + ("tw" tags-tree "+webdev")))) + + (bind! (:map org-mode-map + "RET" nil + "C-j" nil + "C-k" nil + + :i [remap narf/inflate-space-maybe] 'self-insert-command) + + (:map evil-org-mode-map + :ni "A-l" 'org-metaright ; M-j + :ni "A-h" 'org-metaleft ; M-h + :ni "A-k" 'org-metaup ; M-k + :ni "A-j" 'org-metadown ; M-j + :ni "A-l" 'org-shiftmetaright ; M-L + :ni "A-h" 'org-shiftmetaleft ; M-H + :ni "A-k" 'org-shiftmetaup ; M-K + :ni "A-j" 'org-shiftmetadown ; M-J + + :ni "" 'org-beginning-of-line + :ni "" 'org-end-of-line + :ni "" 'org-up-element + :ni "" 'org-down-element + + :ni ", ;" 'helm-org-in-buffer-headings + :ni ", l" 'org-insert-link + :ni "M-a" 'mark-whole-buffer + + :i "C-e" 'org-end-of-line + :i "C-a" 'org-beginning-of-line + :i ;; Add new header line before this line + :i "" 'narf/org-insert-item-before + :i ;; Add new header line after this line + :i "" 'narf/org-insert-item-after + + :i "M-b" (λ (narf/org-surround "*")) ; bold + :i "M-u" (λ (narf/org-surround "_")) ; underline + :i "M-i" (λ (narf/org-surround "/")) ; italics + :i "M-`" (λ (narf/org-surround "+")) ; strikethrough + + :v "M-b" "S*" + :v "M-u" "S_" + :v "M-i" "S/" + :v "M-`" "S+" + + :n ",=" 'org-align-all-tags + :n ",/" 'org-sparse-tree + :n ",?" 'org-tags-view + :n ",a" 'org-attach + :n ",D" 'org-time-stamp-inactive + :n ",T" 'org-show-todo-tree + :n ",d" 'org-time-stamp + :n ",r" 'org-refile + :n ",s" 'org-schedule + :n ",t" 'org-todo + :n "gr" 'org-babel-execute-src-block-maybe + :n "gh" 'outline-up-heading + :n "gj" 'org-forward-heading-same-level + :n "gk" 'org-backward-heading-same-level + :n "gl" 'outline-next-visible-heading + :n "go" 'org-open-at-point + :n "gO" 'org-attach-open + :n "gC-o" 'org-attach-reveal + :n "gI" (λ (if (> (length org-inline-image-overlays) 0) + (org-remove-inline-images) + (org-display-inline-images nil t (line-beginning-position) (line-end-position)))) + :n "gQ" 'org-fill-paragraph + :n "ga" 'org-attach + :n "gA" 'org-agenda + :n "gt" 'org-show-todo-tree + :n "]l" 'org-next-link + :n "[l" 'org-previous-link + :n "$" 'org-end-of-line + :n "^" 'org-beginning-of-line + :n "<" 'org-metaleft + :n ">" 'org-metaright + :n "-" 'org-cycle-list-bullet + :n ",SPC" 'narf/org-toggle-checkbox + :n "," 'org-archive-subtree + :n "" 'narf/org-insert-item-before + :n "" 'narf/org-insert-item-after + :n "RET" (λ (cond ((org-at-item-checkbox-p) + (org-toggle-checkbox)) + ((org-entry-is-todo-p) + (org-todo 'done)))) + :n [tab] 'org-cycle) + + (:after org-agenda + (:map org-agenda-mode-map + :e "" 'org-agenda-Quit + :e "C-j" 'org-agenda-next-item + :e "C-k" 'org-agenda-previous-item + :e "C-n" 'org-agenda-next-item + :e "C-p" 'org-agenda-previous-item)))) + +(provide 'module-org) +;;; module-org.el ends here diff --git a/modules/module-php.el b/modules/module-php.el new file mode 100644 index 000000000..365aeab37 --- /dev/null +++ b/modules/module-php.el @@ -0,0 +1,16 @@ +;;; module-php.el + +(use-package php-mode + :mode "\\.\\(php\\|inc\\)$" + :init + (setq php-template-compatibility nil) + :config + (require 'php-extras) + (add-company-backend! php-mode '(php-extras-company)) + + ;; TODO Tie into emr + (require 'php-refactor-mode) + (add-hook! php-mode '(turn-on-eldoc-mode emr-initialize php-refactor-mode))) + +(provide 'module-php) +;;; module-php.el ends here diff --git a/modules/module-python.el b/modules/module-python.el new file mode 100644 index 000000000..308788881 --- /dev/null +++ b/modules/module-python.el @@ -0,0 +1,75 @@ +;;; module-python.el + +(use-package python + :mode ("\\.py\\'" . python-mode) + :interpreter ("python" . python-mode) + :commands python-mode + :init + (add-hook! python-mode '(narf|enable-tab-width-4 emr-initialize)) + (setq python-indent-offset 4) + (setq python-environment-directory narf-temp-dir) + (setq python-shell-interpreter "ipython") + :config + (define-key python-mode-map (kbd "DEL") nil)) ; interferes with smartparens + +(use-package nose + :commands nose-mode + :preface (defvar nose-mode-map (make-sparse-keymap)) + :init (associate! nose-mode :pattern "/test_.+\\.py\\'") + :config + (bind! :map nose-mode-map + (:prefix "," + :n "tr" 'nosetests-again + :n "ta" 'nosetests-all + :n "ts" 'nosetests-one + :n "tv" 'nosetests-module + :n "tA" 'nosetests-pdb-all + :n "tO" 'nosetests-pdb-one + :n "tV" 'nosetests-pdb-module))) + +(use-package anaconda-mode + :defines (anaconda-mode-map anaconda-nav-mode-map) + :functions (anaconda-mode-running-p) + :init (add-hook! python-mode '(anaconda-mode eldoc-mode)) + :config + (bind! :map anaconda-mode-map :m "gd" 'anaconda-mode-goto-definitions) + (bind! :map anaconda-nav-mode-map :n [escape] 'anaconda-nav-quit) + + (advice-add 'anaconda-mode-doc-buffer :after 'narf*anaconda-mode-doc-buffer) + + (after! company + (require 'company-anaconda) + (add-company-backend! python-mode (anaconda))) + + (after! emr + (emr-declare-command + 'anaconda-mode-view-doc + :title "view documentation" + :modes 'python-mode + :predicate (lambda () (and (anaconda-mode-running-p) + (not (use-region-p)) + (not (sp-point-in-string-or-comment))))) + (emr-declare-command + 'anaconda-mode-goto-assignments + :title "go to assignments" + :modes 'python-mode + :predicate (lambda () (and (anaconda-mode-running-p) + (not (use-region-p)) + (not (sp-point-in-string-or-comment))))) + (emr-declare-command + 'anaconda-mode-goto-definitions + :title "go to definition" + :modes 'python-mode + :predicate (lambda () (and (anaconda-mode-running-p) + (not (use-region-p)) + (not (sp-point-in-string-or-comment))))) + (emr-declare-command + 'anaconda-mode-usages + :title "show usages" + :modes 'python-mode + :predicate (lambda () (and (anaconda-mode-running-p) + (not (use-region-p)) + (not (sp-point-in-string-or-comment))))))) + +(provide 'module-python) +;;; module-python.el ends here diff --git a/modules/module-regex.el b/modules/module-regex.el new file mode 100644 index 000000000..50aded273 --- /dev/null +++ b/modules/module-regex.el @@ -0,0 +1,23 @@ +;;; module-regex.el + +(use-package pcre2el + :functions (rxt--re-builder-switch-pcre-mode) + :after re-builder + :config + (setq reb-re-syntax 'pcre) + (bind! :map rxt-help-mode-map :n [escape] 'kill-buffer-and-window)) + +(use-package re-builder + :commands (re-builder reb-mode-buffer-p) + :config + (add-hook! reb-mode 'narf|reb-cleanup) + (evil-set-initial-state 'reb-mode 'insert) + + (bind! :map reb-mode-map + :n "C-g" 'reb-quit + :n [escape] 'reb-quit + :n [backtab] 'reb-change-syntax)) + + +(provide 'module-regex) +;;; module-regex.el ends here diff --git a/modules/module-ruby.el b/modules/module-ruby.el new file mode 100644 index 000000000..11886f785 --- /dev/null +++ b/modules/module-ruby.el @@ -0,0 +1,111 @@ +;;; module-ruby.el + +(use-package enh-ruby-mode + :mode (("\\.rb$" . enh-ruby-mode) + ("\\.ru$" . enh-ruby-mode) + ("\\.rake$" . enh-ruby-mode) + ("\\.gemspec$" . enh-ruby-mode) + ("\\.?pryrc$" . enh-ruby-mode) + ("/Gemfile$" . enh-ruby-mode) + ("/Capfile$" . enh-ruby-mode) + ("/Vagrantfile$" . enh-ruby-mode) + ("/Rakefile$" . enh-ruby-mode)) + :interpreter "ruby" + :init + (add-hook! enh-ruby-mode 'narf|enable-tab-width-2) + (build-for! enh-ruby-mode "rake %s" "Rakefile") + :config + ;;; Formatting + (setq ruby-indent-level 2 + ruby-deep-indent-paren t + enh-ruby-check-syntax nil) + + (associate! text-mode :match "/\\.rspec$") + + ;; Don't interfere with my custom RET behavior + (define-key enh-ruby-mode-map [?\n] nil) + + (use-package ruby-refactor + :init (add-hook! enh-ruby-mode 'emr-initialize) + :config + (after! emr + (emr-declare-command 'ruby-refactor-extract-to-method + :title "extract method" + :modes 'enh-ruby-mode + :predicate (lambda () (use-region-p))) + (emr-declare-command 'ruby-refactor-extract-local-variable + :title "extract local variable" + :modes 'enh-ruby-mode + :predicate (lambda () (use-region-p))) + (emr-declare-command 'ruby-refactor-extract-constant + :title "extract constant" + :modes 'enh-ruby-mode + :predicate (lambda () (use-region-p))) + (emr-declare-command 'ruby-refactor-add-parameter + :title "add parameter" + :modes 'enh-ruby-mode) + (emr-declare-command 'ruby-refactor-extract-to-let + :title "extract to let" + :modes 'enh-ruby-mode + :predicate (lambda () (use-region-p))))) + + + ;; Rakefiles ;;;;;;;;;;;;;;;;;;;;;;;;;;; + (define-minor-mode rake-mode + "Buffer local minor mode for rake files" + :lighter " Rake" :keymap (make-sparse-keymap) + (add-yas-minor-mode! 'rake-mode)) + (associate! rake-mode :match "/\\(Rakefile\\|\\.rake\\)$") + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ;; Vagrantfiles ;;;;;;;;;;;;;;;;;;;;;;;; + (define-minor-mode vagrant-mode + "Buffer local minor mode for vagrant files" + :lighter " Va" :keymap (make-sparse-keymap) + (add-yas-minor-mode! 'vagrant-mode)) + (associate! vagrant-mode :match "/Vagrantfile$") + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ;; Rspec files ;;;;;;;;;;;;;;;;;;;;;;;;; + (use-package rspec-mode + :defer t + :init + (associate! rspec-mode :match "\\(/spec_helper\\|_spec\\)\\.rb$") + (associate! rspec-mode :match "/\\.rspec$") + + (defvar rspec-mode-verifiable-map (make-sparse-keymap)) + (defvar evilmi-ruby-match-tags + '((("unless" "if") ("elsif" "else") "end") + ("begin" ("rescue" "ensure") "end") + ("case" ("when" "else") "end") + (("class" "def" "while" "do" "module" "for" "until") () "end") + ;; Rake + (("task" "namespace") () "end"))) + :config + (bind! (:prefix "," + :n "tr" 'rspec-rerun + :n "ta" 'rspec-verify-all + :n "ts" 'rspec-verify-single + :n "tv" 'rspec-verify))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + (use-package inf-ruby + :commands (inf-ruby inf-ruby-console-auto) + :config + (evil-set-initial-state 'inf-enh-ruby-mode 'insert) + (after! company + (require 'company-inf-ruby) + (add-company-backend! inf-enh-ruby-mode (inf-ruby)))) + + (use-package robe + :functions (robe-mode robe-start ruby-load-file) + :config + (add-hook! after-save 'narf|ruby-load-file) + (add-hook! enh-ruby-mode 'narf|enable-robe-maybe) + + (after! "company" + (require 'company-robe) + (add-company-backend! enh-ruby-mode (robe))))) + +(provide 'module-ruby) +;;; module-ruby.el ends here diff --git a/modules/module-sass.el b/modules/module-sass.el new file mode 100644 index 000000000..39d0799ee --- /dev/null +++ b/modules/module-sass.el @@ -0,0 +1,29 @@ +;;; module-sass.el --- sass/scss + +(use-package sass-mode + :mode "\\.sass$" + :init (add-hook! sass-mode 'narf|enable-tab-width-2) + :config (after! company (add-company-backend! sass-mode (css)))) + +(use-package scss-mode + :mode "\\.scss$" + :init + (add-hook! scss-mode 'narf|enable-tab-width-2) + (setq-default css-indent-offset 2) + (setq scss-compile-at-save nil) + :config + ;; Syntax coloring breaks on consecutive loads for some reason. This fixes that: + (add-hook! scss-mode 'css-mode) + + (after! web-beautify + (add-hook! scss-mode (setenv "jsbeautify_indent_size" "2")) + (bind! :map scss-mode-map :m "gQ" 'web-beautify-css)) + + (after! company (add-company-backend! scss-mode (css)))) + +(use-package rainbow-mode + :defer t + :init (add-hook! scss-mode 'rainbow-mode)) + +(provide 'module-sass) +;;; module-sass.el ends here diff --git a/modules/module-sonicpi.el b/modules/module-sonicpi.el new file mode 100644 index 000000000..dd62894db --- /dev/null +++ b/modules/module-sonicpi.el @@ -0,0 +1,10 @@ +;;; module-sonicpi.el + +(use-package sonic-pi + :config + (setq sonic-pi-path "/Applications/Sonic Pi.app/") + (add-unreal-buffer! "\\*sonic-pi-server-messages\\*") + (add-popwin-rule! "*sonic-pi-server-messages*" :position bottom :height: 0.4 :nostick t :dedicated t)) + +(provide 'module-sonicpi) +;;; module-sonicpi.el ends here diff --git a/modules/module-swift.el b/modules/module-swift.el new file mode 100644 index 000000000..134a5cb41 --- /dev/null +++ b/modules/module-swift.el @@ -0,0 +1,12 @@ +;;; module-swift.el + +(use-package swift-mode + :mode "\\.swift$" + :config + (after! flycheck (add-to-list 'flycheck-checkers 'swift)) + (after! company (add-company-backend! swift-mode (xcode)))) + +;; TODO Set up emacs task runners for fruitstrap + +(provide 'module-swift) +;;; module-swift.el ends here diff --git a/modules/module-vim.el b/modules/module-vim.el new file mode 100644 index 000000000..42038edf6 --- /dev/null +++ b/modules/module-vim.el @@ -0,0 +1,8 @@ +;;; module-vim.el + +(use-package vimrc-mode + :mode (("/\\.?g?vimrc$" . vimrc-mode) + ("\\.vim$" . vimrc-mode))) + +(provide 'module-vim) +;;; module-vim.el ends here diff --git a/modules/module-web.el b/modules/module-web.el new file mode 100644 index 000000000..2a7cc6abb --- /dev/null +++ b/modules/module-web.el @@ -0,0 +1,83 @@ +;;; module-web.el + +(use-package web-beautify + :commands (web-beautify-js web-beautify-css web-beautify-html) + :init + (after! css-mode + (add-hook! css-mode (setenv "jsbeautify_indent_size" "2")) + (bind! :map css-mode-map :m "gQ" 'web-beautify-css))) + +(use-package web-mode + :mode (("\\.\\(p\\)?htm\\(l\\)?$" . web-mode) + ("\\.tpl\\(\\.php\\)?$" . web-mode) + ("\\.erb$" . web-mode) + ("wp-content/themes/.+/.+\\.php$" . web-mode)) + :init + (add-hook! web-mode 'narf|enable-tab-width-2) + (setq web-mode-markup-indent-offset 2 + web-mode-code-indent-offset 2 + web-mode-css-indent-offset 2 + web-mode-style-padding 2 + web-mode-script-padding 2 + web-mode-block-padding 2) + :config + (after! smartparens + (add-hook! web-mode (setq web-mode-enable-auto-pairing nil)) + + (defun sp-web-mode-is-code-context (id action context) + (when (and (eq action 'insert) + (not (or (get-text-property (point) 'part-side) + (get-text-property (point) 'block-side)))) + t)) + (sp-local-pair 'web-mode "<" nil :when '(sp-web-mode-is-code-context))) + + (after! web-beautify + (add-hook! web-mode (setenv "jsbeautify_indent_size" "4")) + (bind! :map web-mode-map :m "gQ" 'web-beautify-html)) + + (bind! :map web-mode-map + "M-/" 'web-mode-comment-or-uncomment + + :n "zf" 'web-mode-fold-or-unfold + :n ",t" 'web-mode-element-rename + + :nv "]a" 'web-mode-attribute-next + :nv "[a" 'web-mode-attribute-previous + :nv "]t" 'web-mode-tag-next + :nv "[t" 'web-mode-tag-previous + :nv "]T" 'web-mode-element-child + :nv "[T" 'web-mode-element-parent)) + +(use-package emmet-mode + :defer t + :init (add-hook! (scss-mode web-mode html-mode haml-mode nxml-mode) 'emmet-mode) + :config + (setq emmet-move-cursor-between-quotes t) + (bind! :map emmet-mode-keymap + :i "M-e" 'emmet-expand-yas + :i "M-E" 'emmet-expand-line)) + +(define-minor-mode jekyll-mode + "Jekyll development mode." + :init-value nil + :lighter " :{" + :keymap (make-sparse-keymap) + (add-yas-minor-mode! 'jekyll-mode)) +(associate! jekyll-mode + :match "/_\\(layouts\\|posts\\)/.+$" + :files ("config.yml" "_layouts") + :in (web-mode scss-mode html-mode markdown-mode)) +;; (after! company-dict (add-to-list 'company-dict-minor-mode-alist 'jekyll-mode)) + +(define-minor-mode wordpress-mode + "Wordpress development mode." + :init-value nil + :lighter " wp" + :keymap (make-sparse-keymap) + (add-yas-minor-mode! 'wordpress-mode)) +(associate! wordpress-mode :match "/wp-\\(content\\|admin\\|includes\\)/.+$") +(associate! wordpress-mode :match "/wp-.+\\.php$") +;; (after! company-dict (add-to-list 'company-dict-minor-mode-alist 'wordpress-mode)) + +(provide 'module-web) +;;; module-web.el ends here