diff --git a/.gitmodules b/.gitmodules index 2a72adcd6..6b7122738 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,12 +7,6 @@ [submodule "site-lisp/jade-mode"] path = site-lisp/jade-mode url = https://github.com/brianc/jade-mode -[submodule "site-lisp/coffee-mode"] - path = site-lisp/coffee-mode - url = https://github.com/defunkt/coffee-mode -[submodule "site-lisp/mark-multiple"] - path = site-lisp/mark-multiple - url = https://github.com/magnars/mark-multiple.el.git [submodule "site-lisp/ace-jump-mode"] path = site-lisp/ace-jump-mode url = https://github.com/winterTTr/ace-jump-mode.git @@ -82,33 +76,48 @@ [submodule "site-lisp/buster-mode"] path = site-lisp/buster-mode url = https://github.com/magnars/buster-mode.git -[submodule "site-lisp/ruby-end"] - path = site-lisp/ruby-end - url = https://github.com/rejeep/ruby-end.git -[submodule "site-lisp/zencoding"] - path = site-lisp/zencoding - url = https://github.com/rooney/zencoding.git [submodule "site-lisp/change-inner"] path = site-lisp/change-inner url = https://github.com/magnars/change-inner.el.git [submodule "site-lisp/crappy-jsp-mode"] - path = site-lisp/crappy-jsp-mode - url = git://github.com/magnars/crappy-jsp-mode.git + path = site-lisp/crappy-jsp-mode + url = git://github.com/magnars/crappy-jsp-mode.git [submodule "site-lisp/s"] - path = site-lisp/s - url = https://github.com/magnars/s.el.git + path = site-lisp/s + url = https://github.com/magnars/s.el.git [submodule "site-lisp/dash"] - path = site-lisp/dash - url = https://github.com/magnars/dash.el.git + path = site-lisp/dash + url = https://github.com/magnars/dash.el.git [submodule "site-lisp/multifiles"] - path = site-lisp/multifiles - url = https://github.com/magnars/multifiles.el.git + path = site-lisp/multifiles + url = https://github.com/magnars/multifiles.el.git [submodule "site-lisp/tagedit"] - path = site-lisp/tagedit - url = https://github.com/magnars/tagedit.git + path = site-lisp/tagedit + url = https://github.com/magnars/tagedit.git [submodule "site-lisp/fold-this"] - path = site-lisp/fold-this - url = https://github.com/magnars/fold-this.el.git + path = site-lisp/fold-this + url = https://github.com/magnars/fold-this.el.git [submodule "site-lisp/revealjs-mode"] - path = site-lisp/revealjs-mode - url = https://github.com/cjohansen/revealjs-mode.git + path = site-lisp/revealjs-mode + url = https://github.com/cjohansen/revealjs-mode.git +[submodule "site-lisp/clj-refactor"] + path = site-lisp/clj-refactor + url = https://github.com/magnars/clj-refactor.el.git +[submodule "site-lisp/tern"] + path = site-lisp/tern + url = https://github.com/marijnh/tern.git +[submodule "site-lisp/simplezen"] + path = site-lisp/simplezen + url = https://github.com/magnars/simplezen.el.git +[submodule "site-lisp/angular-snippets"] + path = site-lisp/angular-snippets + url = https://github.com/magnars/angular-snippets.el.git +[submodule "site-lisp/flx"] + path = site-lisp/flx + url = https://github.com/lewang/flx.git +[submodule "site-lisp/flycheck"] + path = site-lisp/flycheck + url = https://github.com/lunaryorn/flycheck.git +[submodule "site-lisp/datomic-snippets"] + path = site-lisp/datomic-snippets + url = https://github.com/magnars/datomic-snippets.git diff --git a/.mc-lists.el b/.mc-lists.el index 9f5789b85..fb463b6c9 100644 --- a/.mc-lists.el +++ b/.mc-lists.el @@ -4,12 +4,20 @@ (setq mc/cmds-to-run-for-all '( ac-complete + adv-dash + adv-dot + adv-enter + adv-gt + adv-open-curly + adv-tab back-to-indentation-or-beginning + backward-sexp c-electric-backspace c-electric-delete-forward c-electric-paren c-electric-semi&comma c-electric-slash + c-electric-star change-inner change-number-at-point change-outer @@ -18,9 +26,13 @@ delete-blank-lines dired-back-to-start-of-files duplicate-current-line-or-region + end-of-buffer eval-and-replace + eval-last-sexp fold-this forward-paragraph + forward-sentence + forward-sexp hippie-expand-no-case-fold html-wrap-in-tag isearch-forward-use-region @@ -28,43 +40,121 @@ js2-end-of-line js2-insert-and-indent js2r-inline-var + js2r-move-line-up + js2r-split-string js2r-var-to-this + kill-and-retry-line kill-region-or-backward-word + kill-sexp magit-stage-item markdown-enter-key move-line-down move-line-up + move-text-down + move-text-up + move-to-window-line-top-bottom new-line-above + open-line-above + open-line-below org-beginning-of-line org-delete-backward-char org-delete-char org-end-of-line org-metaleft org-metaright + org-return-indent org-self-insert-command org-shiftright + org-yank orgtbl-self-insert-command + paredit-backslash + paredit-backward + paredit-backward-up + paredit-close-round + paredit-close-square + paredit-comment-dwim + paredit-doublequote + paredit-forward + paredit-forward-delete + paredit-forward-down + paredit-forward-kill-word + paredit-forward-slurp-sexp + paredit-forward-up + paredit-join-sexps + paredit-kill + paredit-kill-region-or-backward-word + paredit-newline + paredit-open-curly + paredit-open-round + paredit-open-square + paredit-raise-sexp + paredit-reindent-defun + paredit-semicolon + paredit-splice-sexp + paredit-split-sexp + paredit-wrap-round + paredit-wrap-round-from-behind + paredit-wrap-square quoted-insert ruby-electric-brace save-region-or-current-line sgml-delete-tag sgml-slash + skeleton-pair-insert-maybe slime-space + sp--self-insert-command + sp-remove-active-pair-overlay + sp-self-insert-command + subtract-number-at-point + tagedit-forward-slurp-tag + tagedit-insert-dot + tagedit-insert-equal + tagedit-insert-exclamation-mark + tagedit-insert-gt + tagedit-insert-hash + tagedit-insert-lt + tagedit-insert-quote + tagedit-kill + tagedit-kill-attribute + tagedit-maybe-insert-slash + tagedit-raise-tag + tagedit-splice-tag + tern-ac-dot-complete + toggle-assert-refute + toggle-quotes + touch-buffer-file + transpose-params + transpose-sexps wrap-region-trigger yank-indented yas/expand + zap-up-to-char )) (setq mc/cmds-to-run-once '( - ace-jump-mode + adv-insert-new-number + cleanup-buffer + describe-key + dired-toggle-read-only + edebug-next-mode eval-expression + goto-line-with-feedback + handle-switch-frame + ido-switch-buffer js2r-extract-var js2r-rename-var - quit-window - sgml-maybe-name-self + jump-between-source-and-test-files + magit-status + mc/add-cursor-on-click + mc/add-cursors-to-all-matches + multiple-cursors-mode + persp-switch + shell smex toggle-read-only view-echo-area-messages wgrep-change-to-wgrep-mode + wgrep-finish-edit + wgrep-save-all-buffers )) diff --git a/README.md b/README.md index 3222defb5..08bd52694 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,7 @@ You can also see some thoughts behind the settings on my [What the .emacs.d!?](h ## Setup -To grab all the dependencies, either: - - git clone git://github.com/magnars/.emacs.d.git - cd .emacs.d - git submodule init - git submodule update - -or on git v1.6.5 or later: +To grab all the dependencies: git clone --recursive git://github.com/magnars/.emacs.d.git @@ -22,21 +15,16 @@ that are best handled by the package manager. ## Install emacs on mac -I use Cocoa Emacs, installed like this: - - brew install emacs --cocoa - -You can also get the very latest Emacs: - - brew install emacs --cocoa --use-git-head --HEAD - -To open it with Alfred or Quicksilver, you have to copy `Emacs.app` into -`/Applications` instead of the symlink that brew places there. +I use [Emacs For Mac OS X](http://emacsformacosx.com). ## Tips for using these emacs settings If you want to use my settings straight out of the box, here are some things to note: + * I recommend starting with a blank emacs + + [Technomancy's better-defaults package](https://github.com/technomancy/better-defaults), + and then dig through this repo for useful nuggets. + * The key bindings are optimized for a norwegian keyboard layout. * Start by reading up on all the cool stuff in key-bindings.el. @@ -49,18 +37,13 @@ If you want to use my settings straight out of the box, here are some things to * `C-h` is rebound to backspace, like in the shell. Get help on `F1` instead. - * Autocomplete with `C-.` + * Autocomplete with `C-.` (autocomplete entire lines with `C-:`) * expand-region is your friend. Find its bound key by doing `F1 f er/expand-region` - * annoying-arrows suggests alternative ways of moving around if you use the - arrow keys excessively. - * Undo with `C-_` and redo with `M-_`. Watch the undo-tree with `C-x u` - * Easily add functions to the F-keys with `M-: (f5 )`, example `(f5 (flush-lines "console.log"))` - - * Quickly jump anywhere in the buffer by pressing `fn` plus the starting letter of a word. + * Quickly jump anywhere in the buffer with `C-ø` then the starting letter of a word. * Indent and clean up white space in the entire buffer with `C-c n` @@ -70,6 +53,26 @@ If you want to use my settings straight out of the box, here are some things to * Watch [emacsrocks.com](http://emacsrocks.com) +### Additional setup + +#### tern.js + +If you want [tern](http://ternjs.net/) in your javascript, you need to +install [node](http://nodejs.org) and run `npm install` in the +`.emacs/site-lisp/tern` directory. + +#### nrepl-inspect + +If you want [nrepl-inspect](https://github.com/vitalreactor/nrepl-inspect) +to work, you need to: + + - Go to `.emacs.d/site-lisp/nrepl-inspect` and do `lein install` + - Configure your `~/.lein/profiles.clj`: + + {:user {:dependencies [[nrepl-inspect "0.3.0"]] + :repl-options {:nrepl-middleware + [inspector.middleware/wrap-inspect]}}} + ## Survival guide for the first week of emacs When you start using emacs for the first time, your habits fight you every inch diff --git a/appearance.el b/appearance.el index 6b5a62930..07d4eb8b5 100644 --- a/appearance.el +++ b/appearance.el @@ -3,22 +3,50 @@ color-theme-is-global t truncate-partial-width-windows nil) -(set-face-background 'region "#464740") - ;; Highlight current line (global-hl-line-mode 1) -;; Customize background color of lighlighted line -(set-face-background 'hl-line "#222222") +;; Set custom theme path +(setq custom-theme-directory (concat user-emacs-directory "themes")) + +(dolist + (path (directory-files custom-theme-directory t "\\w+")) + (when (file-directory-p path) + (add-to-list 'custom-theme-load-path path))) + +;; Default theme +(defun use-presentation-theme () + (interactive) + (disable-theme 'default-black) + (load-theme 'prez) + (when (boundp 'magnars/presentation-font) + (set-face-attribute 'default nil :font magnars/presentation-font))) + +(defun use-default-theme () + (interactive) + (disable-theme 'prez) + (load-theme 'default-black) + (when (boundp 'magnars/default-font) + (set-face-attribute 'default nil :font magnars/default-font))) -;; Highlight in yasnippet -(set-face-background 'yas/field-highlight-face "#333399") +(defun toggle-presentation-mode () + (interactive) + (if (string= (frame-parameter nil 'font) magnars/default-font) + (use-presentation-theme) + (use-default-theme))) + +(global-set-key (kbd "C-") 'toggle-presentation-mode) + +(use-default-theme) ;; Preeeetty font in Emacs 24/Ubuntu (if is-mac nil (set-default-font "DejaVu Sans Mono") (set-face-attribute 'default nil :height 105)) +;; Don't defer screen updates when performing operations +(setq redisplay-dont-pause t) + ;; org-mode colors (setq org-todo-keyword-faces '( @@ -30,21 +58,11 @@ ;; Highlight matching parentheses when the point is on them. (show-paren-mode 1) -;; No menu bars -(menu-bar-mode -1) - (when window-system (setq frame-title-format '(buffer-file-name "%f" ("%b"))) - (turn-off-tool-bar) (tooltip-mode -1) - (turn-off-tool-bar) (blink-cursor-mode -1)) -(add-hook 'before-make-frame-hook 'turn-off-tool-bar) - -;; Ditch them scrollbars -(scroll-bar-mode -1) - ;; Make zooming affect frame instead of buffers (require 'zoom-frm) @@ -52,4 +70,24 @@ (defadvice split-window-right (after balance activate) (balance-windows)) (defadvice delete-window (after balance activate) (balance-windows)) +;; Unclutter the modeline +(require 'diminish) +(eval-after-load "yasnippet" '(diminish 'yas/minor-mode)) +(eval-after-load "eldoc" '(diminish 'eldoc-mode)) +(eval-after-load "paredit" '(diminish 'paredit-mode)) +(eval-after-load "tagedit" '(diminish 'tagedit-mode)) +(eval-after-load "elisp-slime-nav" '(diminish 'elisp-slime-nav-mode)) +(eval-after-load "skewer-mode" '(diminish 'skewer-mode)) +(eval-after-load "skewer-css" '(diminish 'skewer-css-mode)) +(eval-after-load "skewer-html" '(diminish 'skewer-html-mode)) +(eval-after-load "smartparens" '(diminish 'smartparens-mode)) + +(defmacro rename-modeline (package-name mode new-name) + `(eval-after-load ,package-name + '(defadvice ,mode (after rename-modeline activate) + (setq mode-name ,new-name)))) + +(rename-modeline "js2-mode" js2-mode "JS2") +(rename-modeline "clojure-mode" clojure-mode "Clj") + (provide 'appearance) diff --git a/custom.el b/custom.el index 71e982337..32f6d0bec 100644 --- a/custom.el +++ b/custom.el @@ -1,22 +1,34 @@ -(custom-set-faces - ;; custom-set-faces was added by Custom. - ;; If you edit it by hand, you could mess it up, so be careful. - ;; Your init file should contain only one such instance. - ;; If there is more than one, they won't work right. - '(default ((t (:inherit nil :stipple nil :background "Black" :foreground "White" :inverse-video nil :box nil :strike-t*hrough nil :overline nil :underline nil :slant normal :weight normal :width normal :height 105)))) - '(diff-refine-change ((t (:background "midnight blue")))) - '(highlight ((((class color) (min-colors 88) (background dark)) (:background "#111111")))) - '(js2-function-param-face ((t (:foreground "LightGoldenrod")))) - '(mumamo-background-chunk-submode ((((class color) (min-colors 88) (background dark)) nil))) - '(show-paren-match ((nil (:background "#333399")))) - '(show-paren-mismatch ((((class color)) (:background "red"))))) +;; (custom-set-faces +;; ;; custom-set-faces was added by Custom. +;; ;; If you edit it by hand, you could mess it up, so be careful. +;; ;; Your init file should contain only one such instance. +;; ;; If there is more than one, they won't work right. +;; '(default ((t (:inherit nil :stipple nil :background "Black" :foreground "White" :inverse-video nil :box nil :strike-t*hrough nil :overline nil :underline nil :slant normal :weight normal :width nor +;; '(diff-refine-change ((t (:background "midnight blue")))) +;; '(highlight ((((class color) (min-colors 88) (background dark)) (:background "#111111")))) +;; '(js2-function-param-face ((t (:foreground "LightGoldenrod")))) +;; '(mumamo-background-chunk-submode ((((class color) (min-colors 88) (background dark)) nil))) +;; '(show-paren-match ((nil (:background "#333399")))) +;; '(show-paren-mismatch ((((class color)) (:background "red"))))) +;; (custom-set-variables +;; ;; custom-set-variables was added by Custom. +;; ;; If you edit it by hand, you could mess it up, so be careful. +;; ;; Your init file should contain only one such instance. +;; ;; If there is more than one, they won't work right. +;; '(fill-column 80) +;; '(ido-use-filename-at-point nil) +;; '(safe-local-variable-values (quote ((eval font-lock-add-keywords nil (quote (("defexamples\\|def-example-group\\| => " (0 (quote font-lock-keyword-face)))))) (eval when (and (buffer-file-name) (fil +;; '(send-mail-function (quote smtpmail-send-it))) (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. - '(fill-column 80) - '(ido-use-filename-at-point nil) - '(safe-local-variable-values (quote ((eval font-lock-add-keywords nil (quote (("defexamples\\|def-example-group\\| => " (0 (quote font-lock-keyword-face)))))) (eval when (and (buffer-file-name) (file-regular-p (buffer-file-name)) (string-match-p "^[^.]" (buffer-file-name))) (emacs-lisp-mode)) (eval font-lock-add-keywords nil (quote (("defexamples\\| => " (0 (quote font-lock-keyword-face)))))) (encoding . utf-8)))) - '(send-mail-function (quote smtpmail-send-it))) + '(custom-safe-themes (quote ("f3ec2da81c2b1f66f911fe47843a09055754b40fafaddcce79bbd4d781161329" default)))) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + ) diff --git a/defuns/buffer-defuns.el b/defuns/buffer-defuns.el index 51189148f..24ebc063f 100644 --- a/defuns/buffer-defuns.el +++ b/defuns/buffer-defuns.el @@ -34,6 +34,11 @@ (emacs-lisp-mode) )) +(defun split-window-right-and-move-there-dammit () + (interactive) + (split-window-right) + (windmove-right)) + (defun toggle-window-split () (interactive) (if (= (count-windows) 2) @@ -127,37 +132,6 @@ Symbols matching the text at point are put first in the completion list." (push-mark (point)) (goto-char position)))) -;;; These belong in coding-hook: - -;; We have a number of turn-on-* functions since it's advised that lambda -;; functions not go in hooks. Repeatedly evaling an add-to-list with a -;; hook value will repeatedly add it since there's no way to ensure -;; that a lambda doesn't already exist in the list. - -(defun local-column-number-mode () - (make-local-variable 'column-number-mode) - (column-number-mode t)) - -(defun local-comment-auto-fill () - (set (make-local-variable 'comment-auto-fill-only-comments) t) - (auto-fill-mode t)) - -(defun turn-on-hl-line-mode () - (if window-system (hl-line-mode t))) - -(defun turn-on-save-place-mode () - (setq save-place t)) - -(defun turn-on-whitespace () - (whitespace-mode t)) - -(defun turn-off-tool-bar () - (tool-bar-mode -1)) - -(add-hook 'coding-hook 'local-column-number-mode) -(add-hook 'coding-hook 'local-comment-auto-fill) -(add-hook 'coding-hook 'turn-on-hl-line-mode) - (defun untabify-buffer () (interactive) (untabify (point-min) (point-max))) @@ -166,28 +140,27 @@ Symbols matching the text at point are put first in the completion list." (interactive) (indent-region (point-min) (point-max))) -(defun cleanup-buffer-safe () - "Perform a bunch of safe operations on the whitespace content of a buffer. -Does not indent buffer, because it is used for a before-save-hook, and that -might be bad." - (interactive) - (untabify-buffer) - (delete-trailing-whitespace) - (set-buffer-file-coding-system 'utf-8)) - (defun cleanup-buffer () "Perform a bunch of operations on the whitespace content of a buffer. Including indent-buffer, which should not be called automatically on save." (interactive) - (cleanup-buffer-safe) + (untabify-buffer) + (delete-trailing-whitespace) (indent-buffer)) (defun file-name-with-one-directory (file-name) (concat (cadr (reverse (split-string file-name "/"))) "/" (file-name-nondirectory file-name))) +(require 's) + +(defvar user-home-directory (concat (expand-file-name "~") "/")) + +(defun shorter-file-name (file-name) + (s-chop-prefix user-home-directory file-name)) + (defun recentf--file-cons (file-name) - (cons (file-name-with-one-directory file-name) file-name)) + (cons (shorter-file-name file-name) file-name)) (defun recentf-ido-find-file () "Find a recent file using ido." diff --git a/defuns/clj-defuns.el b/defuns/clj-defuns.el index 02ba9ce42..ae0223c5f 100644 --- a/defuns/clj-defuns.el +++ b/defuns/clj-defuns.el @@ -1,32 +1,20 @@ -(defvar clj-project-name "intelliadv" - "Name of the project") +(require 's) -(make-variable-buffer-local 'clj-project-name) +(defun clj--src-file-name-from-test (name) + (s-with name + (s-replace "/test/" "/src/") + (s-replace "_test.clj" ".clj"))) -(defun clj-source-path-snippet () - (concat "/src/" clj-project-name "/")) - -(defun clj-test-path-snippet () - (concat "/test/" clj-project-name "/test/")) - -(defun clj-in-source-file-p () - (string-match-p (clj-source-path-snippet) (buffer-file-name))) - -(defun clj-in-test-file-p () - (string-match-p (clj-test-path-snippet) (buffer-file-name))) +(defun clj--test-file-name-from-src (name) + (s-with name + (s-replace "/src/" "/test/") + (s-replace ".clj" "_test.clj"))) (defun clj-other-file-name () - (when (not (or (clj-in-test-file-p) - (clj-in-source-file-p))) - (error "I can't seem to find my bearings. Where are we again?")) - (or (and (clj-in-source-file-p) - (replace-regexp-in-string (clj-source-path-snippet) - (clj-test-path-snippet) - (buffer-file-name))) - (and (clj-in-test-file-p) - (replace-regexp-in-string (clj-test-path-snippet) - (clj-source-path-snippet) - (buffer-file-name))))) + (let ((name (buffer-file-name))) + (if (string-match-p "/test/" name) + (clj--src-file-name-from-test name) + (clj--test-file-name-from-src name)))) (defun clj-jump-to-other-file (arg) (interactive "P") diff --git a/defuns/editing-defuns.el b/defuns/editing-defuns.el index 914b70ade..00f1d5bd4 100644 --- a/defuns/editing-defuns.el +++ b/defuns/editing-defuns.el @@ -1,4 +1,4 @@ -;; Basic text editing defuns +;;; editing-defuns.el --- Basic text editing defuns -*- lexical-binding: t; -*- (defun open-line-below () (interactive) @@ -21,42 +21,72 @@ (indent-for-tab-command)) (indent-for-tab-command)) +(defun new-line-dwim () + (interactive) + (let ((break-open-pair (or (and (looking-back "{") (looking-at "}")) + (and (looking-back ">") (looking-at "<")) + (and (looking-back "\\[") (looking-at "\\]"))))) + (newline) + (when break-open-pair + (save-excursion + (newline) + (indent-for-tab-command))) + (indent-for-tab-command))) + (defun duplicate-current-line-or-region (arg) "Duplicates the current line or region ARG times. If there's no region, the current line will be duplicated." (interactive "p") - (save-excursion - (if (region-active-p) - (duplicate-region arg) - (duplicate-current-line arg)))) + (if (region-active-p) + (let ((beg (region-beginning)) + (end (region-end))) + (duplicate-region arg beg end) + (one-shot-keybinding "d" (λ (duplicate-region 1 beg end)))) + (duplicate-current-line arg) + (one-shot-keybinding "d" 'duplicate-current-line))) + +(defun one-shot-keybinding (key command) + (set-temporary-overlay-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd key) command) + map) t)) + +(defun replace-region-by (fn) + (let* ((beg (region-beginning)) + (end (region-end)) + (contents (buffer-substring beg end))) + (delete-region beg end) + (insert (funcall fn contents)))) -(defun duplicate-region (num &optional start end) +(defun duplicate-region (&optional num start end) "Duplicates the region bounded by START and END NUM times. If no START and END is provided, the current region-beginning and -region-end is used. Adds the duplicated text to the kill ring." +region-end is used." (interactive "p") - (let* ((start (or start (region-beginning))) - (end (or end (region-end))) - (region (buffer-substring start end))) - (kill-ring-save start end) - (goto-char start) - (dotimes (i num) - (insert region)))) - -(defun duplicate-current-line (num) + (save-excursion + (let* ((start (or start (region-beginning))) + (end (or end (region-end))) + (region (buffer-substring start end))) + (goto-char end) + (dotimes (i num) + (insert region))))) + +(defun duplicate-current-line (&optional num) "Duplicate the current line NUM times." (interactive "p") - (when (eq (point-at-eol) (point-max)) - (goto-char (point-max)) - (newline) - (forward-char -1)) - (duplicate-region num (point-at-bol) (1+ (point-at-eol)))) + (save-excursion + (when (eq (point-at-eol) (point-max)) + (goto-char (point-max)) + (newline) + (forward-char -1)) + (duplicate-region num (point-at-bol) (1+ (point-at-eol))))) ;; automatically indenting yanked text if in programming-modes (require 'dash) (defvar yank-indent-modes '(prog-mode + sgml-mode js2-mode) "Modes in which to indent regions that are yanked (or yank-popped)") @@ -187,18 +217,30 @@ region-end is used. Adds the duplicated text to the kill ring." (goto-char (point-max)) (line-number-at-pos))))) +(require 's) + (defun incs (s &optional num) - (number-to-string (+ (or num 1) (string-to-number s)))) + (let* ((inc (or num 1)) + (new-number (number-to-string (+ inc (string-to-number s)))) + (zero-padded? (s-starts-with? "0" s))) + (if zero-padded? + (s-pad-left (length s) "0" new-number) + new-number))) (defun change-number-at-point (arg) (interactive "p") (unless (or (looking-at "[0-9]") (looking-back "[0-9]")) (error "No number to change at point")) - (while (looking-back "[0-9]") - (forward-char -1)) - (re-search-forward "[0-9]+" nil) - (replace-match (incs (match-string 0) arg) nil nil)) + (save-excursion + (while (looking-back "[0-9]") + (forward-char -1)) + (re-search-forward "[0-9]+" nil) + (replace-match (incs (match-string 0) arg) nil nil))) + +(defun subtract-number-at-point (arg) + (interactive "p") + (change-number-at-point (- arg))) (defun replace-next-underscore-with-camel (arg) (interactive "p") diff --git a/defuns/js2r-defuns.el b/defuns/js2r-defuns.el index 18a279e86..2d9294e61 100644 --- a/defuns/js2r-defuns.el +++ b/defuns/js2r-defuns.el @@ -28,6 +28,17 @@ (jump-to-source-file-other-window arg) (jump-to-test-file-other-window arg))) +;; Duplicate object property node + +(defun js2r-duplicate-object-property-node () + (interactive) + (js2r--guard) + (let ((node (js2r--closest 'js2-object-prop-node-p))) + (goto-char (js2-node-abs-pos node)) + (skip-syntax-backward " >") + (insert (buffer-substring (point) (js2-node-abs-end node)) ",") + (skip-syntax-forward " >"))) + ;; Rename tests and sources (defun js2r--rename-file (old-name new-name) diff --git a/defuns/misc-defuns.el b/defuns/misc-defuns.el index 15211c1f4..24ab2cc45 100644 --- a/defuns/misc-defuns.el +++ b/defuns/misc-defuns.el @@ -26,18 +26,72 @@ (call-interactively 'goto-line)) (linum-mode -1))) +;; start a httpd-server in current directory +(defun httpd-start-here (directory port) + (interactive (list (read-directory-name "Root directory: " default-directory nil t) + (read-number "Port: " 8017))) + (setq httpd-root directory) + (setq httpd-port port) + (httpd-start) + (browse-url (concat "http://localhost:" (number-to-string port) "/"))) + +;; shorthand for interactive lambdas +(defmacro λ (&rest body) + `(lambda () + (interactive) + ,@body)) + +(global-set-key (kbd "s-l") (λ (insert "\u03bb"))) + +;; command to help set up magit-gh-pulls +(defun magit-gh-pulls-setup (repoid) + (interactive "suser/repo: ") + (shell-command "git config --add magit.extension gh-pulls") + (shell-command (concat "git config magit.gh-pulls-repo " repoid))) + +;; Increase/decrease selective display +(defun inc-selective-display (arg) + (interactive "P") + (if (numberp arg) + (set-selective-display arg) + (if (numberp selective-display) + (set-selective-display (+ 2 selective-display)) + (set-selective-display 2))) + (create-temp-selective-display-keymap)) + +(defun dec-selective-display () + (interactive) + (when (and (numberp selective-display) + (> selective-display 2)) + (set-selective-display (- selective-display 2))) + (create-temp-selective-display-keymap)) + +(defun clear-selective-display () + (interactive) + (when (numberp selective-display) + (set-selective-display nil))) + +(defun create-temp-selective-display-keymap () + (set-temporary-overlay-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "+") 'inc-selective-display) + (define-key map (kbd "-") 'dec-selective-display) + (define-key map (kbd "0") 'clear-selective-display) + map)) + (message "Type + to reveal more, - for less, 0 to reset.")) + ;; Add spaces and proper formatting to linum-mode. It uses more room than ;; necessary, but that's not a problem since it's only in use when going to ;; lines. (setq linum-format (lambda (line) - (propertize - (format (concat " %" - (number-to-string - (length (number-to-string - (line-number-at-pos (point-max))))) - "d ") - line) - 'face 'linum))) + (propertize + (format (concat " %" + (number-to-string + (length (number-to-string + (line-number-at-pos (point-max))))) + "d ") + line) + 'face 'linum))) (defun isearch-yank-selection () "Put selection from buffer into search string." diff --git a/defuns/project-defuns.el b/defuns/project-defuns.el new file mode 100644 index 000000000..49e4be44d --- /dev/null +++ b/defuns/project-defuns.el @@ -0,0 +1,11 @@ +(defmacro project-specifics (name &rest body) + (declare (indent 1)) + `(progn + (add-hook 'find-file-hook + (lambda () + (when (string-match-p ,name (buffer-file-name)) + ,@body))) + (add-hook 'dired-after-readin-hook + (lambda () + (when (string-match-p ,name (dired-current-directory)) + ,@body))))) diff --git a/defuns/snippet-helpers.el b/defuns/snippet-helpers.el index 95be116ae..94bfe7814 100644 --- a/defuns/snippet-helpers.el +++ b/defuns/snippet-helpers.el @@ -31,7 +31,7 @@ (substring (buffer-file-name) (length eproject-root)))))))) (defun snippet--clojure-namespace-under-test () - (replace-regexp-in-string ".test." "." (snippet--clojure-namespace-from-buffer-file-name))) + (replace-regexp-in-string "-test" "" (snippet--clojure-namespace-from-buffer-file-name))) ;; snippet-helper-helpers diff --git a/init.el b/init.el index 43647271e..a987a29db 100644 --- a/init.el +++ b/init.el @@ -14,6 +14,16 @@ (add-to-list 'load-path user-emacs-directory) (add-to-list 'load-path site-lisp-dir) +;; Keep emacs Custom-settings in separate file +(setq custom-file (expand-file-name "custom.el" user-emacs-directory)) +(load custom-file) + +;; Are we on a mac? +(setq is-mac (equal system-type 'darwin)) + +;; Set up appearance early +(require 'appearance) + ;; Settings for currently logged in user (setq user-settings-dir (concat user-emacs-directory "users/" user-login-name)) @@ -24,10 +34,6 @@ (when (file-directory-p project) (add-to-list 'load-path project))) -;; Keep emacs Custom-settings in separate file -(setq custom-file (expand-file-name "custom.el" user-emacs-directory)) -(load custom-file) - ;; Write backup files to own directory (setq backup-directory-alist `(("." . ,(expand-file-name @@ -41,33 +47,31 @@ (setq-default save-place t) (setq save-place-file (expand-file-name ".places" user-emacs-directory)) -;; Are we on a mac? -(setq is-mac (equal system-type 'darwin)) - -;; Setup elnode before packages to stop it from starting a server -;;(require 'setup-elnode) - ;; Setup packages (require 'setup-package) ;; Install extensions if they're missing (defun init--install-packages () (packages-install - (cons 'exec-path-from-shell melpa) - (cons 'magit melpa) - (cons 'paredit melpa) - (cons 'move-text melpa) - (cons 'gist melpa) - (cons 'htmlize melpa) - (cons 'elisp-slime-nav melpa) - ;(cons 'elnode marmalade) - (cons 'slime-js marmalade) - (cons 'git-commit-mode melpa) - (cons 'gitconfig-mode melpa) - (cons 'gitignore-mode melpa) - (cons 'clojure-mode melpa) - (cons 'clojure-test-mode melpa) - (cons 'nrepl melpa))) + '(magit + paredit + move-text + gist + htmlize + visual-regexp + flycheck + smartparens + ido-vertical-mode + simple-httpd + nodejs-repl + restclient + highlight-escape-sequences + elisp-slime-nav + git-commit-mode + gitconfig-mode + gitignore-mode + clojure-mode + nrepl))) (condition-case nil (init--install-packages) @@ -79,7 +83,9 @@ (require 'sane-defaults) ;; Setup environment variables from the user's shell. -(when is-mac (exec-path-from-shell-initialize)) +(when is-mac + (require-package 'exec-path-from-shell) + (exec-path-from-shell-initialize)) ;; Setup extensions (eval-after-load 'ido '(require 'setup-ido)) @@ -95,15 +101,26 @@ (require 'setup-html-mode) (require 'setup-paredit) +;; Default setup of smartparens +(require 'smartparens-config) +(setq sp-autoescape-string-quote nil) +(--each '(css-mode-hook + restclient-mode-hook + js-mode-hook + markdown-mode) + (add-hook it 'turn-on-smartparens-mode)) + ;; Language specific setup files (eval-after-load 'js2-mode '(require 'setup-js2-mode)) (eval-after-load 'ruby-mode '(require 'setup-ruby-mode)) (eval-after-load 'clojure-mode '(require 'setup-clojure-mode)) (eval-after-load 'markdown-mode '(require 'setup-markdown-mode)) -;; Load slime-js when asked for -(autoload 'slime-js-jack-in-browser "setup-slime-js" nil t) -(autoload 'slime-js-jack-in-node "setup-slime-js" nil t) +;; Load stuff on demand +(autoload 'skewer-start "setup-skewer" nil t) +(autoload 'skewer-demo "setup-skewer" nil t) +(autoload 'flycheck-mode "setup-flycheck" nil t) +(autoload 'auto-complete-mode "auto-complete" nil t) ;; Map files to modes (require 'mode-mappings) @@ -111,6 +128,16 @@ ;; Calendar stuff (require 'setup-calendar) +;; Highlight escape sequences +(require 'highlight-escape-sequences) +(hes-mode) +(put 'font-lock-regexp-grouping-backslash 'face-alias 'font-lock-builtin-face) + +;; Visual regexp +(require 'visual-regexp) +(define-key global-map (kbd "M-&") 'vr/query-replace) +(define-key global-map (kbd "M-/") 'vr/replace) + ;; Functions (load all files in defuns-dir) (setq defuns-dir (expand-file-name "defuns" user-emacs-directory)) (dolist (file (directory-files defuns-dir t "\\w+")) @@ -145,14 +172,13 @@ (require 'key-bindings) ;; Misc -(require 'appearance) +(require 'project-archetypes) (require 'my-misc) (when is-mac (require 'mac)) ;; Elisp go-to-definition with M-. and back again with M-, (autoload 'elisp-slime-nav-mode "elisp-slime-nav") -(add-hook 'emacs-lisp-mode-hook (lambda () (elisp-slime-nav-mode t))) -(eval-after-load 'elisp-slime-nav '(diminish 'elisp-slime-nav-mode)) +(add-hook 'emacs-lisp-mode-hook (lambda () (elisp-slime-nav-mode t) (eldoc-mode 1))) ;; Email, baby (require 'setup-mu4e) @@ -164,12 +190,14 @@ ;; Run at full power please (put 'downcase-region 'disabled nil) +(put 'upcase-region 'disabled nil) (put 'narrow-to-region 'disabled nil) ;; Diminish modeline clutter (require 'diminish) (diminish 'yas/minor-mode) +;; Unicode without the hassle (require 'unicode-mode) ;; Conclude init by setting up specifics for the current user diff --git a/key-bindings.el b/key-bindings.el index c30359b85..32707a77e 100644 --- a/key-bindings.el +++ b/key-bindings.el @@ -6,6 +6,10 @@ ;; Completion that uses many different methods to find options. (global-set-key (kbd "C-.") 'hippie-expand-no-case-fold) (global-set-key (kbd "C-:") 'hippie-expand-lines) +(global-set-key (kbd "C-,") 'completion-at-point) + +(require 'misc) +(global-set-key (kbd "s-.") 'copy-from-above-command) ;; Smart M-x (global-set-key (kbd "M-x") 'smex) @@ -38,6 +42,13 @@ (global-set-key (kbd "s-Å") 'mc/mark-previous-symbol-like-this) (global-set-key (kbd "M-s-Æ") 'mc/mark-all-symbols-like-this) +;; Extra multiple cursors stuff +(global-set-key (kbd "C-~") 'mc/reverse-regions) +(global-set-key (kbd "M-~") 'mc/sort-regions) +(global-set-key (kbd "H-~") 'mc/insert-numbers) + +(global-set-key (kbd "C-S-") 'mc/add-cursor-on-click) + ;; Set anchor to start rectangular-region-mode (global-set-key (kbd "C-M-SPC") 'set-rectangular-region-anchor) @@ -61,6 +72,8 @@ (define-key key-translation-map [?\C-h] [?\C-?]) (global-set-key (kbd "") 'help-command) +(global-set-key (kbd "M-h") 'kill-region-or-backward-word) + ;; Transpose stuff with M-t (global-unset-key (kbd "M-t")) ;; which used to be transpose-words (global-set-key (kbd "M-t l") 'transpose-lines) @@ -68,6 +81,9 @@ (global-set-key (kbd "M-t s") 'transpose-sexps) (global-set-key (kbd "M-t p") 'transpose-params) +;; Interactive selective display +(global-set-key (kbd "C-x $") 'inc-selective-display) + ;; Change next underscore with a camel case (global-set-key (kbd "C-c C--") 'replace-next-underscore-with-camel) (global-set-key (kbd "M-s M--") 'snakeify-current-word) @@ -79,7 +95,7 @@ ;; Use M-w for copy-line if no active region (global-set-key (kbd "M-w") 'save-region-or-current-line) -(global-set-key (kbd "M-W") '(lambda () (interactive) (save-region-or-current-line 1))) +(global-set-key (kbd "M-W") '(λ (save-region-or-current-line 1))) ;; Make shell more convenient, and suspend-frame less (global-set-key (kbd "C-z") 'shell) @@ -87,11 +103,15 @@ ;; Zap to char (global-set-key (kbd "M-z") 'zap-up-to-char) +(global-set-key (kbd "s-z") (lambda (char) (interactive "cZap up to char backwards: ") (zap-up-to-char -1 char))) + (global-set-key (kbd "M-Z") 'zap-to-char) +(global-set-key (kbd "s-Z") (lambda (char) (interactive "cZap to char backwards: ") (zap-to-char -1 char))) ;; iy-go-to-char - like f in Vim (global-set-key (kbd "M-m") 'jump-char-forward) (global-set-key (kbd "M-M") 'jump-char-backward) +(global-set-key (kbd "s-m") 'jump-char-backward) ;; vim's ci and co commands (global-set-key (kbd "M-I") 'change-inner) @@ -101,6 +121,9 @@ (define-key global-map (kbd "C-+") 'zoom-frm-in) (define-key global-map (kbd "C--") 'zoom-frm-out) +(global-set-key (kbd "s-i") 'copy-inner) +(global-set-key (kbd "s-o") 'copy-outer) + ;; Create new frame (define-key global-map (kbd "C-x C-n") 'make-frame-command) @@ -117,6 +140,13 @@ (global-set-key (kbd "M-`") 'file-cache-minibuffer-complete) (global-set-key (kbd "C-x C-b") 'ibuffer) +;; toggle two most recent buffers +(fset 'quick-switch-buffer [?\C-x ?b return]) +(global-set-key (kbd "s-b") 'quick-switch-buffer) + +;; Revert without any fuss +(global-set-key (kbd "M-") (λ (revert-buffer t t))) + ;; Edit file with sudo (global-set-key (kbd "M-s e") 'sudo-edit) @@ -125,15 +155,17 @@ ;; Window switching (windmove-default-keybindings) ;; Shift+direction -(global-set-key (kbd "C-x -") 'rotate-windows) -(global-set-key (kbd "C-x C--") 'toggle-window-split) +(global-set-key (kbd "C-x -") 'toggle-window-split) +(global-set-key (kbd "C-x C--") 'rotate-windows) (global-unset-key (kbd "C-x C-+")) ;; don't zoom like this +(global-set-key (kbd "C-x 3") 'split-window-right-and-move-there-dammit) + ;; Add region to *multifile* (global-set-key (kbd "C-!") 'mf/mirror-region-in-multifile) ;; Indentation help -(global-set-key (kbd "M-j") (lambda () (interactive) (join-line -1))) +(global-set-key (kbd "M-j") (λ (join-line -1))) ;; Help should search more than just commands (global-set-key (kbd " a") 'apropos) @@ -177,12 +209,15 @@ (global-set-key (kbd "C-S-r") 'isearch-backward) ;; Move more quickly -(global-set-key (kbd "C-S-n") (lambda () (interactive) (next-line 5))) -(global-set-key (kbd "C-S-p") (lambda () (interactive) (previous-line 5))) -(global-set-key (kbd "C-S-f") (lambda () (interactive) (forward-char 5))) -(global-set-key (kbd "C-S-b") (lambda () (interactive) (backward-char 5))) -;; Convenience on ThinkPad Keyboard: Use back/forward as pg up/down +(global-set-key (kbd "C-S-n") (λ (ignore-errors (next-line 5)))) +(global-set-key (kbd "C-S-p") (λ (ignore-errors (previous-line 5)))) +(global-set-key (kbd "C-S-f") (λ (ignore-errors (forward-char 5)))) +(global-set-key (kbd "C-S-b") (λ (ignore-errors (backward-char 5)))) + +(global-set-key (kbd "H-*") 'beginning-of-buffer) ;; H-p +(global-set-key (kbd "H-n") 'end-of-buffer) +;; Convenience on ThinkPad Keyboard: Use back/forward as pg up/down (global-set-key (kbd "") 'scroll-down) (global-set-key (kbd "") 'scroll-up) (global-set-key (kbd "") 'beginning-of-buffer) @@ -198,7 +233,7 @@ (global-set-key (kbd "C-c u") 'uncomment-region) ;; Eval buffer -(global-set-key (kbd "C-c v") 'eval-buffer) +(global-set-key (kbd "C-c C-k") 'eval-buffer) ;; Create scratch buffer (global-set-key (kbd "C-c b") 'create-scratch-buffer) @@ -219,7 +254,7 @@ ;; Clever newlines (global-set-key (kbd "") 'open-line-below) (global-set-key (kbd "") 'open-line-above) -(global-set-key (kbd "") 'new-line-in-between) +(global-set-key (kbd "") 'new-line-dwim) ;; Duplicate region (global-set-key (kbd "C-c d") 'duplicate-current-line-or-region) @@ -244,6 +279,8 @@ ;; Increase number at point (or other change based on prefix arg) (global-set-key (kbd "C-M-+") 'change-number-at-point) +(global-set-key (kbd "C-?") 'subtract-number-at-point) +(eval-after-load 'undo-tree '(define-key undo-tree-map (kbd "C-?") nil)) ;; Browse the kill ring (global-set-key (kbd "C-x C-y") 'browse-kill-ring) @@ -255,7 +292,7 @@ ;; Jump from file to containing directory (global-set-key (kbd "C-x C-j") 'dired-jump) (autoload 'dired-jump "dired") -(global-set-key (kbd "C-x M-j") '(lambda () (interactive) (dired-jump 1))) +(global-set-key (kbd "C-x M-j") '(λ (dired-jump 1))) ;; Easy-mode fullscreen rgrep (global-set-key (kbd "M-s s") 'git-grep-fullscreen) @@ -278,6 +315,7 @@ (global-unset-key (kbd "C-x C-o")) ;; which used to be delete-blank-lines (also bound to C-c C-) (global-set-key (kbd "C-x C-o ja") (ffip-create-pattern-file-finder "*.java")) (global-set-key (kbd "C-x C-o js") (ffip-create-pattern-file-finder "*.js")) +(global-set-key (kbd "C-x C-o ht") (ffip-create-pattern-file-finder "*.html")) (global-set-key (kbd "C-x C-o jp") (ffip-create-pattern-file-finder "*.jsp")) (global-set-key (kbd "C-x C-o cs") (ffip-create-pattern-file-finder "*.css")) (global-set-key (kbd "C-x C-o cl") (ffip-create-pattern-file-finder "*.clj")) @@ -288,6 +326,10 @@ (global-set-key (kbd "C-x C-o ph") (ffip-create-pattern-file-finder "*.php")) (global-set-key (kbd "C-x C-o tx") (ffip-create-pattern-file-finder "*.txt")) (global-set-key (kbd "C-x C-o vm") (ffip-create-pattern-file-finder "*.vm")) +(global-set-key (kbd "C-x C-o xm") (ffip-create-pattern-file-finder "*.xml")) +(global-set-key (kbd "C-x C-o pr") (ffip-create-pattern-file-finder "*.properties")) +(global-set-key (kbd "C-x C-o in") (ffip-create-pattern-file-finder "*.ini")) +(global-set-key (kbd "C-x C-o gr") (ffip-create-pattern-file-finder "*.groovy")) ;; View occurrence in occur mode (define-key occur-mode-map (kbd "v") 'occur-mode-display-occurrence) diff --git a/mac.el b/mac.el index 29adee21a..c91e4a580 100644 --- a/mac.el +++ b/mac.el @@ -1,14 +1,76 @@ +(require 'dash) + ;; change command to meta, and ignore option to use weird Norwegian keyboard -(setq mac-option-modifier 'none) +(setq mac-option-modifier 'super) (setq mac-command-modifier 'meta) (setq ns-function-modifier 'hyper) -;; mac friendly font -(set-face-attribute 'default nil :font "Monaco-16") +;; Norwegian mac-keyboard alt-keys) +(define-key key-translation-map (kbd "s-8") (kbd "[")) +(define-key key-translation-map (kbd "s-(") (kbd "{")) +(define-key key-translation-map (kbd "s-9") (kbd "]")) +(define-key key-translation-map (kbd "s-)") (kbd "}")) +(define-key key-translation-map (kbd "s-7") (kbd "|")) +(define-key key-translation-map (kbd "s-/") (kbd "\\")) +(define-key key-translation-map (kbd "M-s-7") (kbd "M-|")) + +(global-set-key (kbd "s-u") 'universal-argument) +(global-set-key (kbd "s--") 'negative-argument) +(--dotimes 5 (global-set-key (read-kbd-macro (format "s-%d" it)) 'digit-argument)) + +;; redefine read-char, at least for invocation from elisp +(defun read-char (&optional prompt) ;; (inherit-input-method seconds) + "Read a character from the command input (keyboard or macro). + It is returned as a number. + If the character has modifiers, they are resolved and reflected to the + character code if possible (e.g. C-SPC -> 0). -;; make sure path is correct when launched as application -(setenv "PATH" (concat "/usr/local/bin:" (getenv "PATH"))) -(push "/usr/local/bin" exec-path) + If the user generates an event which is not a character (i.e. a mouse + click or function key event), `read-char' signals an error. As an + exception, switch-frame events are put off until non-character events + can be read. + If you want to read non-character events, or ignore them, call + `read-event' or `read-char-exclusive' instead. + + If the optional argument PROMPT is non-nil, display that as a prompt. + If the optional argument INHERIT-INPUT-METHOD is non-nil and some + input method is turned on in the current buffer, that input method + is used for reading a character. + If the optional argument SECONDS is non-nil, it should be a number + specifying the maximum number of seconds to wait for input. If no + input arrives in that time, return nil. SECONDS may be a + floating-point value." + ;; if (! NILP (prompt)) + ;; message_with_string ("%s", prompt, 0); + ;; val = read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), + ;; seconds); + ;; return (NILP (val) ? Qnil + ;; : make_number (char_resolve_modifier_mask (XINT (val)))); + (let ((inherit-input-method nil) (seconds nil)) + ;; `read-key' doesn't explicitly inhibit the input method, but in + ;; practice it disables at least quail input methods because it + ;; binds overriding-terminal-local-map. + (if inherit-input-method (error "Not implemented")) + (catch 'read-char-exclusive + (let ((timer (when seconds + (run-with-timer seconds nil + (lambda () + (throw 'read-char-exclusive nil)))))) + (unwind-protect + (let ((event (read-key prompt))) + (if (numberp event) + event + (setq unread-command-events + (nconc (mapcar 'identity (this-single-command-raw-keys)) + unread-command-events)) + (error "Non-character input-event"))) + (when timer (cancel-timer timer))))))) + +;; mac friendly font +(when window-system + (setq magnars/default-font "-apple-Monaco-medium-normal-normal-*-16-*-*-*-m-0-iso10646-1") + (setq magnars/presentation-font "-apple-Monaco-medium-normal-normal-*-28-*-*-*-m-0-iso10646-1") + (set-face-attribute 'default nil :font magnars/default-font)) ;; keybinding to toggle full screen mode (global-set-key (quote [M-f10]) (quote ns-toggle-fullscreen)) diff --git a/mode-mappings.el b/mode-mappings.el index 6823534bb..fc69d95ba 100644 --- a/mode-mappings.el +++ b/mode-mappings.el @@ -9,6 +9,9 @@ ;; CSS (add-to-list 'auto-mode-alist '("\\.scss$" . css-mode)) +;; Restclient +(add-to-list 'auto-mode-alist '("\\.restclient$" . restclient-mode)) + ;; Cucumber (autoload 'feature-mode "feature-mode") (add-to-list 'auto-mode-alist '("\\.feature$" . feature-mode)) @@ -76,6 +79,7 @@ (autoload 'js2-mode "js2-mode" nil t) (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) (add-to-list 'auto-mode-alist '("\\.json$" . javascript-mode)) +(add-to-list 'auto-mode-alist '("\\.jshintrc$" . javascript-mode)) (add-to-list 'magic-mode-alist '("#!/usr/bin/env node" . js2-mode)) ;; Configuration files diff --git a/my-misc.el b/my-misc.el index 2bd3c3854..0d1e783f8 100644 --- a/my-misc.el +++ b/my-misc.el @@ -1,6 +1,18 @@ ;; Seed the random-number generator (random t) +;; Keep region when undoing in region +(defadvice undo-tree-undo (around keep-region activate) + (if (use-region-p) + (let ((m (set-marker (make-marker) (mark))) + (p (set-marker (make-marker) (point)))) + ad-do-it + (goto-char p) + (set-mark m) + (set-marker p nil) + (set-marker m nil)) + ad-do-it)) + ;; Whitespace-style (setq whitespace-style '(trailing lines space-before-tab indentation space-after-tab) @@ -15,7 +27,8 @@ ""]))) ;; Various superfluous white-space. Just say no. -(add-hook 'before-save-hook 'cleanup-buffer-safe) +(add-hook 'before-save-hook 'whitespace-cleanup) +(add-hook 'makefile-mode-hook 'indent-tabs-mode) ;; Newline after inserting closing tag in html-mode (defadvice sgml-close-tag (after close-tag-then-newline activate) diff --git a/project-archetypes/clj-ring-archetype.el b/project-archetypes/clj-ring-archetype.el new file mode 100644 index 000000000..a493d87e9 --- /dev/null +++ b/project-archetypes/clj-ring-archetype.el @@ -0,0 +1,14 @@ +(defun create-clj-ring (project-name) + (interactive "sProject name: ") + (pa-with-new-project project-name "clj-ring" + ((cons "__project-name__" project-name) + (cons "__project_name__" (s-snake-case project-name))))) + +(defun pa--testing-fn () + (shell-command "rm -rf ~/projects/test-test" pa-out) + (create-clj-ring "test-test") + (find-file-other-window "~/projects/test-test")) + +(pa-declare-project-archetype "clj-ring" 'create-clj-ring) + +(provide 'clj-ring-archetype) diff --git a/project-archetypes/clj-ring/.gitignore b/project-archetypes/clj-ring/.gitignore new file mode 100644 index 000000000..cc2ff397f --- /dev/null +++ b/project-archetypes/clj-ring/.gitignore @@ -0,0 +1,12 @@ +/target +/lib +/classes +/checkouts +pom.xml +pom.xml.asc +*.jar +*.class +.lein-deps-sum +.lein-failures +.lein-plugins +.lein-repl-history diff --git a/project-archetypes/clj-ring/resources/public/css/reset.css b/project-archetypes/clj-ring/resources/public/css/reset.css new file mode 100644 index 000000000..c8e980d28 --- /dev/null +++ b/project-archetypes/clj-ring/resources/public/css/reset.css @@ -0,0 +1,2 @@ +/* Eric Meyer's Reset CSS v2.0 - http://cssreset.com */ +html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0} \ No newline at end of file diff --git a/project-archetypes/clj-ring/src/__project_name__/core.clj b/project-archetypes/clj-ring/src/__project_name__/core.clj new file mode 100644 index 000000000..2fb1d7381 --- /dev/null +++ b/project-archetypes/clj-ring/src/__project_name__/core.clj @@ -0,0 +1,17 @@ +(ns __project-name__.core + (:use compojure.core) + (:use hiccup.core) + (:use hiccup.page) + (:require [compojure.route :as route])) + +(defn render-index [] + (html5 + [:head + [:meta {:charset "utf-8"}] + [:meta {:name "viewport" + :content "width=device-width, initial-scale=1.0, maximum-scale=1"}]])) + +(defroutes app + (GET "/" [] (render-index)) + (route/resources "/") + (route/not-found "

Page not found

")) diff --git a/project-archetypes/emacs-package-archetype.el b/project-archetypes/emacs-package-archetype.el new file mode 100644 index 000000000..e5fa7a9dc --- /dev/null +++ b/project-archetypes/emacs-package-archetype.el @@ -0,0 +1,10 @@ +(defun create-emacs-package (project-name description) + (interactive "sProject name: \nsDescription: ") + (pa-with-new-project project-name "emacs-package" + ((cons "__project-name__" project-name) + (cons "__description__" description)) + (pa-sh "carton"))) + +(pa-declare-project-archetype "emacs-package" 'create-emacs-package) + +(provide 'emacs-package-archetype) diff --git a/project-archetypes/emacs-package/.gitignore b/project-archetypes/emacs-package/.gitignore new file mode 100644 index 000000000..6ea3795c8 --- /dev/null +++ b/project-archetypes/emacs-package/.gitignore @@ -0,0 +1,4 @@ +*.elc +.rvmrc +/TAGS +elpa diff --git a/project-archetypes/emacs-package/.travis.yml b/project-archetypes/emacs-package/.travis.yml new file mode 100644 index 000000000..70ee4d35c --- /dev/null +++ b/project-archetypes/emacs-package/.travis.yml @@ -0,0 +1,22 @@ +language: emacs-lisp +before_install: + - if [ "$EMACS" = 'emacs-snapshot' ]; then + sudo add-apt-repository -y ppa:cassou/emacs && + sudo apt-get update -qq && + sudo apt-get install -qq + emacs-snapshot-el emacs-snapshot-gtk emacs-snapshot; + fi + - if [ "$EMACS" = 'emacs24' ]; then + sudo add-apt-repository -y ppa:cassou/emacs && + sudo apt-get update -qq && + sudo apt-get install -qq + emacs24 emacs24-el emacs24-common-non-dfsg; + fi + - curl -fsSkL https://raw.github.com/rejeep/carton/master/go | sh + - export PATH="/home/travis/.carton/bin:$PATH" + - carton +env: + - EMACS=emacs24 TAGS="--tags ~@requires-e24-3" + - EMACS=emacs-snapshot TAGS="" +script: + ./run-travis-ci.sh diff --git a/project-archetypes/emacs-package/Carton b/project-archetypes/emacs-package/Carton new file mode 100644 index 000000000..938143881 --- /dev/null +++ b/project-archetypes/emacs-package/Carton @@ -0,0 +1,7 @@ +(source "melpa" "http://melpa.milkbox.net/packages/") + +(package-file "__project-name__.el") + +(development + (depends-on "ecukes") + (depends-on "espuds")) diff --git a/project-archetypes/emacs-package/README.md b/project-archetypes/emacs-package/README.md new file mode 100644 index 000000000..c4565733b --- /dev/null +++ b/project-archetypes/emacs-package/README.md @@ -0,0 +1,59 @@ +# __project-name__.el [![Build Status](https://secure.travis-ci.org/magnars/__project-name__.el.png)](http://travis-ci.org/magnars/__project-name__.el) + +__description__ + +## Installation + +I highly recommend installing __project-name__ through elpa. + +It's available on [marmalade](http://marmalade-repo.org/) and +[melpa](http://melpa.milkbox.net/): + + M-x package-install __project-name__ + +You can also install the dependencies on your own, and just dump +__project-name__ in your path somewhere: + + - s.el + - dash.el + +## Contribute + +Yes, please do. :-) + +All changes must be accompanied by feature tests, or I might break it later. +They are written in [Ecukes](http://ecukes.info), a Cucumber for Emacs. + +You'll find the repo at: + + https://github.com/magnars/__project-name__.el + +To fetch the test dependencies, install +[carton](https://github.com/rejeep/carton) if you haven't already, +then: + + $ cd /path/to/__project-name__ + $ carton + +Run the tests with: + + $ ./run-tests.sh + +## License + +Copyright (C) 2013 Magnar Sveen + +Author: Magnar Sveen + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/project-archetypes/emacs-package/__project-name__.el b/project-archetypes/emacs-package/__project-name__.el new file mode 100644 index 000000000..51a10c966 --- /dev/null +++ b/project-archetypes/emacs-package/__project-name__.el @@ -0,0 +1,29 @@ +;;; __project-name__.el --- __description__ + +;; Copyright (C) 2013 Magnar Sveen + +;; Author: Magnar Sveen +;; Version: 0.1.0 +;; Package-Requires: ((s "1.4.0") (dash "1.2.0")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; __description__ + +;;; Code: + +(provide '__project-name__) +;;; __project-name__.el ends here diff --git a/project-archetypes/emacs-package/features/__project-name__.feature b/project-archetypes/emacs-package/features/__project-name__.feature new file mode 100644 index 000000000..c0b465c59 --- /dev/null +++ b/project-archetypes/emacs-package/features/__project-name__.feature @@ -0,0 +1,3 @@ +Feature: + + Scenario: diff --git a/project-archetypes/emacs-package/features/step-definitions/__project-name__-steps.el b/project-archetypes/emacs-package/features/step-definitions/__project-name__-steps.el new file mode 100644 index 000000000..59ced727f --- /dev/null +++ b/project-archetypes/emacs-package/features/step-definitions/__project-name__-steps.el @@ -0,0 +1,23 @@ +(eval-when-compile (require 'cl)) + +(When "^I place the cursor after \"\\(.+\\)\"$" + (lambda (arg) + (goto-char (point-min)) + (let ((search (search-forward arg nil t)) + (message "Can not place cursor after '%s', because there is no such point: '%s'")) + (assert search nil message arg (espuds-buffer-contents))))) + +(When "^I place the cursor before \"\\(.+\\)\"$" + (lambda (arg) + (goto-char (point-max)) + (let ((search (search-backward arg nil t)) + (message "Can not place cursor before '%s', because there is no such point: '%s'")) + (assert search nil message arg (espuds-buffer-contents))))) + +(When "^I go to the \\(front\\|end\\) of the word \"\\(.+\\)\"$" + (lambda (pos word) + (goto-char (point-min)) + (let ((search (re-search-forward (format "%s" word) nil t)) + (message "Can not go to character '%s' since it does not exist in the current buffer: %s")) + (assert search nil message word (espuds-buffer-contents)) + (if (string-equal "front" pos) (backward-word))))) diff --git a/project-archetypes/emacs-package/features/support/env.el b/project-archetypes/emacs-package/features/support/env.el new file mode 100644 index 000000000..1b03fe971 --- /dev/null +++ b/project-archetypes/emacs-package/features/support/env.el @@ -0,0 +1,19 @@ +(let* ((current-directory (file-name-directory load-file-name)) + (features-directory (expand-file-name ".." current-directory)) + (project-directory (expand-file-name ".." features-directory))) + (setq __project-name__-root-path project-directory)) + +(add-to-list 'load-path __project-name__-root-path) + +(require '__project-name__) +(require 'espuds) +(require 'ert) + +(Before + (switch-to-buffer + (get-buffer-create "*__project-name__*")) + (erase-buffer) + (fundamental-mode) + (deactivate-mark)) + +(After) diff --git a/project-archetypes/emacs-package/run-tests.sh b/project-archetypes/emacs-package/run-tests.sh new file mode 100755 index 000000000..f0a3eca25 --- /dev/null +++ b/project-archetypes/emacs-package/run-tests.sh @@ -0,0 +1,3 @@ +#!/bin/sh -e +ECUKES=$(find elpa/ecukes-*/ecukes | tail -1) +carton exec "$ECUKES" "$@" diff --git a/project-archetypes/emacs-package/run-travis-ci.sh b/project-archetypes/emacs-package/run-travis-ci.sh new file mode 100755 index 000000000..db1119a43 --- /dev/null +++ b/project-archetypes/emacs-package/run-travis-ci.sh @@ -0,0 +1,13 @@ +#!/bin/sh -e + +cd "$(dirname "$0")" + +ECUKES_EMACS=${EMACS:-$(which emacs)} +export ECUKES_EMACS + +echo "*** Emacs version ***" +echo "ECUKES_EMACS = $ECUKES_EMACS" +"$ECUKES_EMACS" --version +echo + +exec ./run-tests.sh $TAGS diff --git a/project-archetypes/emacs-package/watch-tests.watchr b/project-archetypes/emacs-package/watch-tests.watchr new file mode 100644 index 000000000..d1f2762c5 --- /dev/null +++ b/project-archetypes/emacs-package/watch-tests.watchr @@ -0,0 +1,45 @@ +ENV["WATCHR"] = "1" +system 'clear' + +def run(cmd) + `#{cmd}` +end + +def run_all_tests + system('clear') + result = run "./run-tests.sh" + puts result +end + +def run_test(file) + system('clear') + result = run "./run-tests.sh #{file} --verbose" + puts result +end + +run_all_tests +watch('.*.feature') { |file| run_test file } +watch('.*.el') { run_all_tests } + +# Ctrl-\ +Signal.trap 'QUIT' do + puts " --- Running all tests ---\n\n" + run_all_tests +end + +@interrupted = false + +# Ctrl-C +Signal.trap 'INT' do + if @interrupted then + @wants_to_quit = true + abort("\n") + else + puts "Interrupt a second time to quit" + @interrupted = true + Kernel.sleep 1.5 + # raise Interrupt, nil # let the run loop catch it + run_all_tests + @interrupted = false + end +end diff --git a/project-archetypes/emacs-snippets-archetype.el b/project-archetypes/emacs-snippets-archetype.el new file mode 100644 index 000000000..c342296c0 --- /dev/null +++ b/project-archetypes/emacs-snippets-archetype.el @@ -0,0 +1,13 @@ +(defun create-emacs-snippets (target name website major-mode) + (interactive "sSnippets for (short name): \nsSnippets for (full name): \nsWebsite: \naMajor mode: ") + (pa-with-new-project (format "%s-snippets" target) "emacs-snippets" + ((cons "__target__" target) + (cons "__name__" name) + (cons "__website__" website) + (cons "__major-mode__" (format "%S" major-mode)) + (cons "__year__" (format-time-string "%Y"))) + (pa-sh "carton package"))) + +(pa-declare-project-archetype "emacs-snippets" 'create-emacs-snippets) + +(provide 'emacs-snippets-archetype) diff --git a/project-archetypes/emacs-snippets/Carton b/project-archetypes/emacs-snippets/Carton new file mode 100644 index 000000000..2d4bfcdff --- /dev/null +++ b/project-archetypes/emacs-snippets/Carton @@ -0,0 +1,3 @@ +(source "melpa" "http://melpa.milkbox.net/packages/") + +(package-file "__target__-snippets.el") diff --git a/project-archetypes/emacs-snippets/README.md b/project-archetypes/emacs-snippets/README.md new file mode 100644 index 000000000..e21d316f2 --- /dev/null +++ b/project-archetypes/emacs-snippets/README.md @@ -0,0 +1,45 @@ +# __target__-snippets.el + +Yasnippets for [__name__](__website__). + +## Installation + +I highly recommend installing __target__-snippets through elpa. + +It's available on [melpa](http://melpa.milkbox.net/): + + M-x package-install __target__-snippets + +You can also install the dependencies on your own, and just dump +__target__-snippets in your path somewhere: + + - s.el + - dash.el + +## Usage + +TODO: Write some stuff about available snippets. + +## Setup + +Well, you'll have to require it. You'll also need +[yasnippets](https://github.com/capitaomorte/yasnippet) of course. + + (require '__target__-snippets) + +## License + +Copyright (C) __year__ Magnar Sveen + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/project-archetypes/emacs-snippets/__target__-snippets.el b/project-archetypes/emacs-snippets/__target__-snippets.el new file mode 100644 index 000000000..92db475b2 --- /dev/null +++ b/project-archetypes/emacs-snippets/__target__-snippets.el @@ -0,0 +1,71 @@ +;;; __target__-snippets.el --- Yasnippets for __name__ + +;; Copyright (C) __year__ Magnar Sveen + +;; Author: Magnar Sveen +;; Keywords: snippets +;; Version: 0.1.0 +;; Package-Requires: ((s "1.4.0") (dash "1.2.0") (yasnippet "0.6.1")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Yasnippets for [__name__](__website__). +;; +;; Please visit README.md for more commentary. + +;;; Code: + +;;;###autoload +(defun __target__-snippets-show-docs-at-point () + (interactive) + (__target__-snippets/show-docs (__target__-snippets/closest-__target__-identifer))) + +(defvar __target__-snippets/docstrings + '(("key" . "docstring") + ("key" . "docstring"))) + +(defvar __target__-snippets/docstrings-regexp + (regexp-opt (-map 'car __target__-snippets/docstrings))) + +(defun -aget (alist key) + (cdr (assoc key alist))) + +(defun __target__-snippets/show-docs (id) + (message (-aget __target__-snippets/docstrings id)) + nil) + +(defun __target__-snippets/closest-__target__-identifer () + (save-excursion + (search-forward " ") + (search-backward-regexp __target__-snippets/docstrings-regexp) + (match-string-no-properties 0))) + +(setq __target__-snippets-root (file-name-directory (or load-file-name + (buffer-file-name)))) + +;;;###autoload +(defun __target__-snippets-initialize () + (let ((snip-dir (expand-file-name "snippets" __target__-snippets-root))) + (when (boundp 'yas-snippet-dirs) + (add-to-list 'yas-snippet-dirs snip-dir t)) + (yas/load-directory snip-dir))) + +;;;###autoload +(eval-after-load "yasnippet" + '(__target__-snippets-initialize)) + +(provide '__target__-snippets) +;;; __target__-snippets.el ends here diff --git a/project-archetypes/emacs-snippets/snippets/__major-mode__/example-snippet-with-docs b/project-archetypes/emacs-snippets/snippets/__major-mode__/example-snippet-with-docs new file mode 100644 index 000000000..1ce233a2e --- /dev/null +++ b/project-archetypes/emacs-snippets/snippets/__major-mode__/example-snippet-with-docs @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: example +# key: example +# -- +example` +(__target__-snippets/show-docs "example")` \ No newline at end of file diff --git a/project-archetypes/js-buster-browser-archetype.el b/project-archetypes/js-buster-browser-archetype.el new file mode 100644 index 000000000..98b6ac481 --- /dev/null +++ b/project-archetypes/js-buster-browser-archetype.el @@ -0,0 +1,16 @@ +(require 'magit) + +(defun create-js-buster-browser (project-name description global) + (interactive "sProject name: \nsDescription: \nsGlobal namespace: ") + (pa-with-new-project project-name "js-buster-browser" + ((cons "__project-name__" project-name) + (cons "__description__" description) + (cons "__GLOBAL__" global)) + (magit-ignore-file ".rvmrc" nil t) + (magit-ignore-file "todo.org" nil t) + (pa-sh "npm link buster") + (pa-sh "npm install"))) + +(pa-declare-project-archetype "js-buster-browser" 'create-js-buster-browser) + +(provide 'js-buster-browser-archetype) diff --git a/project-archetypes/js-buster-browser/.gitignore b/project-archetypes/js-buster-browser/.gitignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/project-archetypes/js-buster-browser/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/project-archetypes/js-buster-browser/.rvmrc b/project-archetypes/js-buster-browser/.rvmrc new file mode 100644 index 000000000..5c8d101eb --- /dev/null +++ b/project-archetypes/js-buster-browser/.rvmrc @@ -0,0 +1 @@ +rvm use 1.9.2@autotest --create \ No newline at end of file diff --git a/project-archetypes/js-buster-browser/README.md b/project-archetypes/js-buster-browser/README.md new file mode 100644 index 000000000..3f50b8f2d --- /dev/null +++ b/project-archetypes/js-buster-browser/README.md @@ -0,0 +1,8 @@ +# __project-name__ + +__description__ + +## License + +Copyright © 2013, Magnar Sveen. uses semantic versioning. Code +released under the BSD license. diff --git a/project-archetypes/js-buster-browser/autolint.js b/project-archetypes/js-buster-browser/autolint.js new file mode 100644 index 000000000..c5d44e88b --- /dev/null +++ b/project-archetypes/js-buster-browser/autolint.js @@ -0,0 +1,26 @@ +module.exports = { + "paths": [ + "test/**/*.js", + "lib/**/*.js" + ], + + "linterOptions": { + "indent": 2, + "vars": true, + "nomen": true, + "sloppy": true, + "plusplus": true, + "predef": [ + "assert", + "refute", + "buster", + "cull", + "dome", + "__GLOBAL__" + ] + }, + + "excludes": [ + "external" + ] +}; diff --git a/project-archetypes/js-buster-browser/buster.js b/project-archetypes/js-buster-browser/buster.js new file mode 100644 index 000000000..a8e5a285b --- /dev/null +++ b/project-archetypes/js-buster-browser/buster.js @@ -0,0 +1,8 @@ +exports["Browser tests"] = { + environment: "browser", + libs: ["external/cull.js", "external/dome.js"], + sources: ["lib/*.js"], + tests: ["test/*.js"], + extensions: [require("buster-lint")], + "buster-lint": require("./autolint") +}; diff --git a/project-archetypes/js-buster-browser/external/cull.js b/project-archetypes/js-buster-browser/external/cull.js new file mode 100644 index 000000000..4e35ed96c --- /dev/null +++ b/project-archetypes/js-buster-browser/external/cull.js @@ -0,0 +1,492 @@ +var cull = (function (global) { + "use strict"; + + var slice = Array.prototype.slice; + var toString = Object.prototype.toString; + + function _assert(pred, msg) { + if (!pred) { throw new TypeError(msg); } + } + + function _refute(pred, msg) { + _assert(!pred, msg); + } + + /** Is `list` an object with a numeric length, but not a DOM element? */ + function isList(list) { + return !!list && + typeof list === "object" && + typeof list.length === "number" && + !list.tagName; + } + + /** Returns a version of `value` that is an actual Array. */ + function toList(value) { + if (toString.call(value) === "[object Array]") { return value; } + if (toString.call(value) === "[object Arguments]") { return slice.call(value); } + if (typeof value === "undefined" || value === null) { return []; } + return slice.call(arguments); + } + + /** Calls `fn` on every item in `list`, presumably for side-effects. */ + function doall(fn, list) { + var i, l; + for (i = 0, l = list.length; i < l; ++i) { + fn(list[i], i, list); + } + } + + /** Is `fn` a function? */ + function isFunction(fn) { + return typeof fn === "function"; + } + + /** + * Returns the result of applying `fn` to `initial` and the first + * item in `list`, then applying `fn` to that result and the 2nd + * item, etc. + * + * Can also be called without `initial`, in which case the first + * invocation of `fn` will be with the first two items in `list`. + */ + function reduce(fn, initial, items) { + _assert(typeof fn === "function", "reducer should be a function"); + var i = 0, l, list = items, accumulator = initial; + + if (arguments.length === 2) { + list = initial; + accumulator = list[0]; + i = 1; + } + + if (typeof list === "string") { list = list.split(""); } + _assert(isList(list), "reduce needs to work on a list"); + + for (l = list.length; i < l; ++i) { + accumulator = fn(accumulator, list[i]); + } + + return accumulator; + } + + /** Is `pred` truthy for all items in `list`? */ + function all(pred, list) { + var i, l; + for (i = 0, l = list.length; i < l; ++i) { + if (!pred(list[i])) { return false; } + } + return true; + } + + /** Is `pred` truthy for any items in `list`? */ + function some(pred, list) { + var i, l; + for (i = 0, l = list.length; i < l; ++i) { + if (pred(list[i])) { return true; } + } + return false; + } + + /** + * Is `pred` truthy for at least one item in `list`, and also falsy + * for at least one item in `list`? + */ + function onlySome(pred, list) { + var i, l, t, f; + for (i = 0, l = list.length; i < l; ++i) { + if (pred(list[i])) { + t = true; + } else { + f = true; + } + if (t && f) { return true; } + } + return false; + } + + /** Returns `string` with white space at either end removed. */ + function trim(string) { + return (string.trim && string.trim()) || + string.replace(/^\s+|\s+$/, ""); + } + + /** Returns `arg` unchanged. */ + function identity(arg) { return arg; } + + /** Is `o` neither undefined nor null? */ + function defined(o) { return typeof o !== "undefined" && o !== null; } + + /** Returns a version of `fn` that only accepts one argument. */ + function unary(fn) { + return function (arg) { + return fn.call(this, arg); + }; + } + + /** + * Returns a function that takes one argument and returns its + * `name`-property. + */ + function prop(name) { + return function (object) { + return object[name]; + }; + } + + /** + * Returns a function that takes one argument and calls its + * `name`-function with `args` (optional). + */ + function func(name, args) { + return function (object) { + return object[name].apply(object, toList(args)); + }; + } + + /** + * Returns a function that takes one argument and returns true if + * it is equal to `x`. + */ + function eq(x) { + return function (y) { return x === y; }; + } + + var composeSignature = "compose takes func|[funcs] " + + "and optional thisp object"; + + /** + * Returns a function that calls the last function in `fns`, then + * calls the second to last function in `fns` with the result of + * the first, and so on, with an optional this-binding in `thisp`. + */ + function compose(fns, thisp) { + _refute(isFunction(thisp) || arguments.length > 2, composeSignature); + + var _fns = toList(fns); + + _assert(all(isFunction, _fns), composeSignature); + + return function () { + var i = _fns.length; + var result = arguments; + while (i--) { + result = [_fns[i].apply(thisp || this, result)]; + } + return result[0]; + }; + } + + /** + * Takes any number of arguments, and returns a function that + * takes one function and calls it with the arguments. + */ + function callWith() { + var args = arguments; + return function (fn) { + return fn.apply(this, args); + }; + } + + /** + * Takes a function `fn` and any number of additional arguments, + * fewer than the normal arguments to `fn`, and returns a + * function. When called, the returned function calls `fn` with + * the given arguments first and then additional args. + */ + function partial(fn) { + var args = slice.call(arguments, 1); + return function () { + return fn.apply(this, args.concat(slice.call(arguments))); + }; + } + + /** + * Returns a function that calls `callee` with `obj` as this. + * `callee` can be a function, or it can be a string - in which + * case it will be used to look up a method on `obj`. + * + * Optionally takes additional arguments that are partially + * applied. + */ + function bind(obj, callee) { + var fn = typeof callee === "string" ? obj[callee] : callee; + var args = slice.call(arguments, 2); + return function () { + return fn.apply(obj, args.concat(slice.call(arguments))); + }; + } + + /** Flatten `list` recursively and return a list of non-list values */ + function flatten(list) { + _assert(isList(list), "flatten expects a list"); + var res = [], i, l; + + for (i = 0, l = list.length; i < l; i++) { + res = res.concat(isList(list[i]) ? flatten(list[i]) : list[i]); + } + + return res; + } + + /** Return the first index of `needle` in `list`, otherwise < 0 */ + function indexOf(needle, list) { + _assert(isList(list), "indexOf expects a needle and a list"); + var i, l; + for (i = 0, l = list.length; i < l; ++i) { + if (needle === list[i]) { return i; } + } + return -1; + } + + /** Return a list with only the unique values in `list` */ + function uniq(list) { + _assert(isList(list), "uniq expects a list"); + var result = [], i, l; + + for (i = 0, l = list.length; i < l; ++i) { + if (indexOf(list[i], result) < 0) { + result.push(list[i]); + } + } + + return result; + } + + /** Return the first item in `list` for which `fn` returns `true` */ + function first(fn, list) { + _assert(isFunction(fn) && isList(list), + "first expects a function and a list"); + + var i, l; + for (i = 0, l = list.length; i < l; ++i) { + if (fn(list[i])) { + return list[i]; + } + } + } + + /** Return a new list containing the items from `list` for which + `fn` is `true` */ + function select(fn, list) { + _assert(isFunction(fn) && isList(list), + "select expects a function and a list"); + var result = [], i, l; + for (i = 0, l = list.length; i < l; ++i) { + if (fn(list[i])) { + result.push(list[i]); + } + } + return result; + } + + /** Return a list of properties present in `list` but not in `other` */ + function difference(list, other) { + _assert(isList(list) && isList(other), "difference expects two lists"); + return select(function (value) { + return indexOf(value, other) < 0; + }, list); + } + + /** Return a list of enumerable own property keys in `object` */ + function keys(object) { + var prop, result = []; + for (prop in object) { + if (object.hasOwnProperty(prop)) { + result.push(prop); + } + } + return result; + } + + /** Return a list of enumerable own property values in `object` */ + function values(object) { + var prop, result = []; + for (prop in object) { + if (object.hasOwnProperty(prop)) { + result.push(object[prop]); + } + } + return result; + } + + /** Return a list of non-{null, undefined} items in `list` */ + var seldef = partial(select, defined); + + /** + * Returns a new list consisting of the result of applying `fn` to + * the items in `list`. + */ + function map(fn, list) { + var result = [], i, l; + for (i = 0, l = list.length; i < l; i++) { + result.push(fn(list[i])); + } + return result; + } + + /** + * Returns the complement of `pred`, ie a function that returns true + * when `pred` would be falsy, and false when `pred` would be truthy. + */ + function negate(pred) { + return function () { + return !pred.apply(this, arguments); + }; + } + + /** + * Returns a new list of the items in `list` for which `pred` + * returns nil. + */ + function reject(pred, list) { + return select(negate(pred), list); + } + + /** + * Returns a new list with the concatenation of the elements in + * `list1` and `list2`. + */ + function concat(list1, list2) { + return toList(list1).concat(toList(list2)); + } + + /** + * Returns a new list with the items in `list` grouped into + * `n-`sized sublists. + * + * The last group may contain less than `n` items. + */ + function partition(n, list) { + var result = [], i, l; + for (i = 0, l = list.length; i < l; i += n) { + result.push(list.slice(i, i + n)); + } + return result; + } + + /** + * Returns a new list consisting of the result of applying `fn` to + * the items in `list`, but filtering out all null or undefined + * values from both `list` and the resulting list. + */ + function mapdef(fn, list) { + return seldef(map(fn, seldef(list))); + } + + /** + * Returns the result of applying concat to the result of applying + * map to `fn` and `list`. Thus function `fn` should return a + * collection. + */ + function mapcat(fn, list) { + return reduce(concat, map(fn, list)); + } + + /** + * Returns a new list of all elements in `list` separated by + * `sep`. + */ + function interpose(sep, list) { + var result = [], i, l; + for (i = 0, l = list.length; i < l; i += 1) { + result.push(list[i]); + if (i < l - 1) { + result.push(sep); + } + } + return result; + } + + // cull.advice + + /** + * Advices the method `name` on `obj`, calling `fn` after the + * method is called. `fn` is called with the return value of the + * method as its first argument, then the methods original + * arguments. If `fn` returns anything, it will override the + * return value of the method. + */ + function after(obj, name, fn) { + var originalFn = obj[name]; + obj[name] = function () { + var ret1 = originalFn.apply(this, arguments); + var ret2 = fn.apply(this, [ret1].concat(slice.call(arguments))); + return typeof ret2 !== "undefined" ? ret2 : ret1; + }; + } + + /** + * Advices the method `name` on `obj`, calling `fn` before the + * method is called. `fn` is called with the same arguments as the + * method. + */ + function before(obj, name, fn) { + var originalFn = obj[name]; + obj[name] = function () { + fn.apply(this, arguments); + return originalFn.apply(this, arguments); + }; + } + + /** + * Advices the method `name` on `obj`, calling `fn` instead of the + * method. `fn` receives the original method as its first + * argument, and then the methods original arguments. It is up to + * the advicing function if and how the original method is called. + */ + function around(obj, name, fn) { + var f = partial(fn, obj[name]); + obj[name] = function () { + return f.apply(this, arguments); + }; + } + + /** docs:function-list */ + return { + _assert: _assert, + _refute: _refute, + trim: trim, + doall: doall, + reduce: reduce, + all: all, + some: some, + onlySome: onlySome, + isFunction: isFunction, + isList: isList, + toList: toList, + identity: identity, + defined: defined, + unary: unary, + prop: prop, + func: func, + eq: eq, + compose: compose, + callWith: callWith, + partial: partial, + bind: bind, + keys: keys, + values: values, + concat: concat, + flatten: flatten, + uniq: uniq, + first: first, + select: select, + negate: negate, + reject: reject, + seldef: seldef, + map: map, + mapdef: mapdef, + mapcat: mapcat, + partition: partition, + difference: difference, + interpose: interpose, + indexOf: indexOf, + after: after, + before: before, + around: around + }; +}(this)); + +if (typeof require === "function" && typeof module !== "undefined") { + module.exports = cull; +} \ No newline at end of file diff --git a/project-archetypes/js-buster-browser/external/dome.js b/project-archetypes/js-buster-browser/external/dome.js new file mode 100644 index 000000000..fb6bd52f9 --- /dev/null +++ b/project-archetypes/js-buster-browser/external/dome.js @@ -0,0 +1,321 @@ +var dome = (function (C) { + function _assert(pred, msg) { + if (!pred) { throw new TypeError(msg); } + } + + function _refute(pred, msg) { + _assert(!pred, msg); + } + + function children(elements) { + if (C.isList(elements)) { return C.flatten(C.map(children, elements)); } + var results = [], child = elements.firstChild; + while (child) { + if (child.nodeType === 1) { results.push(child); } + child = child.nextSibling; + } + return results; + } + + function id(idStr) { + return document.getElementById(idStr); + } + + function byClass(className, parent) { + var ctx = parent || document; + if (ctx.getElementsByClassName) { + return ctx.getElementsByClassName(className); + } + var elements = ctx.getElementsByTagName("*"), i, l, result = []; + var regexp = new RegExp("(^|\\s)" + className + "(\\s|$)"); + for (i = 0, l = elements.length; i < l; ++i) { + if (regexp.test(elements[i].className)) { + result.push(elements[i]); + } + } + return result; + } + + function remove(element) { + element.parentNode.removeChild(element); + } + + function hasClassName(className, element) { + var regexp = new RegExp("(^|\\s)" + className + "(\\s|$)"); + return regexp.test(element.className); + } + + function addClassName(cn, element) { + if (C.isList(element)) { + return C.doall(C.partial(addClassName, cn), element); + } + if (hasClassName(cn, element)) { return; } + element.className = C.trim(element.className + " " + cn); + } + + function removeClassName(cn, element) { + if (C.isList(element)) { + return C.doall(C.partial(removeClassName, cn), element); + } + if (!hasClassName(cn, element)) { return; } + var regexp = new RegExp("(^|\\s)" + cn + "(\\s|$)"); + element.className = C.trim(element.className.replace(regexp, " ")); + } + + // Implementation from jQuery/Sizzle. Simplified. + function text(elm) { + _assert(typeof elm !== "undefined" && + typeof elm.nodeType === "number", + "text() expects DOM element"); + var nodeType = elm.nodeType; + + if (nodeType === 1 || nodeType === 9 || nodeType === 11) { + // Use textContent for elements + // innerText usage removed for consistency of new lines + // (see jQuery #11153) + if (typeof elm.textContent === "string") { + return elm.textContent; + } + var ret = ""; + for (elm = elm.firstChild; elm; elm = elm.nextSibling) { + ret += text(elm); + } + return ret; + } + if (nodeType === 3 || nodeType === 4) { + return elm.nodeValue; + } + return ""; + } + + function frag(items) { + var fragment = document.createDocumentFragment(); + C.doall(C.bind(fragment, "appendChild"), C.toList(items)); + return fragment; + } + + var el; + + var isContent = function (content) { + return content !== null && typeof content !== "undefined" && + (typeof content.nodeType !== "undefined" || + typeof content === "string" || + C.isList(content)); + }; + + function setData(data, element) { + var name; + data = data || {}; + + for (name in data) { + if (data.hasOwnProperty(name)) { + element.setAttribute("data-" + name, data[name]); + element["data-" + name] = data[name]; + } + } + } + + function getData(property, element) { + return element.getAttribute("data-" + property); + } + + var propmap = { + style: function (element, styles) { + var property; + for (property in styles) { + if (styles.hasOwnProperty(property)) { + element.style[property] = styles[property]; + } + } + }, + + data: function (el, data) { + setData(data, el); + } + }; + + function setProp(properties, element) { + var name, mapper; + properties = properties || {}; + + for (name in properties) { + if (properties.hasOwnProperty(name)) { + mapper = propmap[name]; + if (mapper) { + mapper(element, properties[name]); + } else { + element[name] = properties[name]; + } + } + } + } + + function append(content, element) { + _assert(isContent(content), + "Content should be one or a list of [string, DOM element]"); + content = C.toList(content); + var i, l; + for (i = 0, l = content.length; i < l; ++i) { + if (typeof content[i] === "string") { + element.appendChild(document.createTextNode(content[i])); + } else { + element.appendChild(content[i]); + } + } + } + + function setContent(children, element) { + _assert(element && typeof element.innerHTML !== "undefined", + "setContent() needs element"); + element.innerHTML = ""; + append(children, element); + } + + el = function (tagName, attrProps, content) { + _refute(arguments.length > 3, + "Content should be one or a list of [string, DOM element]"); + if (!content && isContent(attrProps)) { + return el(tagName, {}, attrProps); + } + _refute(attrProps && attrProps.tagName, + "Cannot set attribute property tagName. Use a list when " + + "adding multiple content elements."); + var element = document.createElement(tagName); + setProp(attrProps, element); + append(content || [], element); + return element; + }; + + el.toString = function () { + return "dome.el()"; + }; + + C.doall(function (tagName) { el[tagName] = C.partial(el, tagName); }, [ + "a", "br", "div", "fieldset", "form", "h2", "h3", "h4", + "h5", "img", "input", "label", "li", "p", "span", "strong", + "textarea", "ul", "span", "select", "option", "ol", "iframe", + "table", "tr", "td", "pre", "button", "i" + ]); + + /** docs:function-list */ + return { + propmap: propmap, + el: el, + setProp: setProp, + append: append, + setContent: setContent, + children: children, + id: id, + byClass: byClass, + remove: remove, + frag: frag, + text: text, + data: { get: getData, set: setData }, + cn: { has: hasClassName, add: addClassName, rm: removeClassName } + }; +}(this.cull)); + +/*global cull, dome, window*/ + +// This is a modified version of code by Juriy Zaytsev originally published at +// http://msdn.microsoft.com/en-us/magazine/ff728624.aspx +(function (C, D) { + function isHostMethod(object, method) { + return (/^(?:function|object|unknown)$/).test(typeof object[method]); + } + + var getUniqueId = (function () { + if (typeof document.documentElement.uniqueID !== "undefined") { + return function (element) { + return element.uniqueID; + }; + } + var uid = 0; + return function (element) { + if (!element.__uniqueID) { + element.__uniqueID = "uniqueID__" + uid; + uid += 1; + } + return element.__uniqueID; + }; + }()); + + var elements = {}, on, off, d = document.documentElement; + + function createWrappedHandler(uid, handler) { + return function (e) { + handler.call(elements[uid], e || window.event); + }; + } + + function createListener(uid, handler) { + return { + handler: handler, + wrappedHandler: createWrappedHandler(uid, handler) + }; + } + + if (isHostMethod(d, "addEventListener") && + isHostMethod(d, "removeEventListener") && + isHostMethod(window, "addEventListener") && + isHostMethod(window, "removeEventListener")) { + on = function (element, eventName, handler) { + element.addEventListener(eventName, handler, false); + return { + cancel: function () { off(element, eventName, handler); } + }; + }; + + off = function (element, eventName, handler) { + element.removeEventListener(eventName, handler, false); + }; + } else if (isHostMethod(d, "attachEvent") && + isHostMethod(d, "detachEvent") && + isHostMethod(window, "attachEvent") && + isHostMethod("detachEvent")) { + var listeners = {}; + + on = function (element, eName, handler) { + var uid = getUniqueId(element); + elements[uid] = element; + if (!listeners[uid]) { listeners[uid] = {}; } + if (!listeners[uid][eName]) { listeners[uid][eName] = []; } + var listener = createListener(uid, handler); + listeners[uid][eName].push(listener); + element.attachEvent("on" + eName, listener.wrappedHandler); + + return { cancel: function () { off(element, eName, handler); } }; + }; + + off = function (element, eName, handler) { + var uid = getUniqueId(element); + if (!listeners[uid] || !listeners[uid][eName]) { return; } + listeners[uid][eName] = C.select(function (listener) { + if (listener.handler !== handler) { return true; } + element.detachEvent("on" + eName, listener.wrappedHandler); + }, listeners[uid][eName]); + }; + } + + function delegate(delegator, element, event, handler) { + on(element, event, function (e) { + if (delegator(e.target, event, e)) { + handler.call(e.target, e); + } + }); + } + + delegate.bycn = function (className, element, event, handler) { + delegate(C.partial(D.cn.has, className), element, event, handler); + }; + + dome.on = on; + dome.off = off; + dome.delegate = delegate; + + dome.propmap.events = function (el, events) { + C.doall(function (prop) { + on(el, prop, events[prop]); + }, C.keys(events)); + }; +}(cull, dome)); \ No newline at end of file diff --git a/project-archetypes/js-buster-browser/lib/main.js b/project-archetypes/js-buster-browser/lib/main.js new file mode 100644 index 000000000..60742c826 --- /dev/null +++ b/project-archetypes/js-buster-browser/lib/main.js @@ -0,0 +1 @@ +var __GLOBAL__ = this.__GLOBAL__ || {}; \ No newline at end of file diff --git a/project-archetypes/js-buster-browser/package.json b/project-archetypes/js-buster-browser/package.json new file mode 100644 index 000000000..884070142 --- /dev/null +++ b/project-archetypes/js-buster-browser/package.json @@ -0,0 +1,10 @@ +{ + "name": "__project-name__", + "version": "0.1.0", + "description": "__description__", + "author": { "name": "Magnar Sveen" }, + "devDependencies": { + "buster": "~0.6", + "buster-lint": "~0" + } +} diff --git a/project-archetypes/js-buster-browser/run-tests.sh b/project-archetypes/js-buster-browser/run-tests.sh new file mode 100755 index 000000000..8ea210862 --- /dev/null +++ b/project-archetypes/js-buster-browser/run-tests.sh @@ -0,0 +1 @@ +buster test -F warning diff --git a/project-archetypes/js-buster-browser/test/main-test.js b/project-archetypes/js-buster-browser/test/main-test.js new file mode 100644 index 000000000..5bb322f72 --- /dev/null +++ b/project-archetypes/js-buster-browser/test/main-test.js @@ -0,0 +1,7 @@ +(function () { + buster.testCase("Main", { + "Your blank slate, Sir": function () { + assert(true); + } + }); +}()); \ No newline at end of file diff --git a/project-archetypes/js-buster-browser/todo.org b/project-archetypes/js-buster-browser/todo.org new file mode 100644 index 000000000..05093beeb --- /dev/null +++ b/project-archetypes/js-buster-browser/todo.org @@ -0,0 +1,2 @@ +* Todo [0/1] +** TODO Write a README diff --git a/project-archetypes/js-buster-browser/watch-tests.watchr b/project-archetypes/js-buster-browser/watch-tests.watchr new file mode 100644 index 000000000..a87acb51b --- /dev/null +++ b/project-archetypes/js-buster-browser/watch-tests.watchr @@ -0,0 +1,38 @@ +ENV["WATCHR"] = "1" +system 'clear' + +def run(cmd) + `#{cmd}` +end + +def run_all_tests + system('clear') + result = run "./run-tests.sh" + puts result +end + +run_all_tests +watch('.*.js') { run_all_tests } + +# Ctrl-\ +Signal.trap 'QUIT' do + puts " --- Running all tests ---\n\n" + run_all_tests +end + +@interrupted = false + +# Ctrl-C +Signal.trap 'INT' do + if @interrupted then + @wants_to_quit = true + abort("\n") + else + puts "Interrupt a second time to quit" + @interrupted = true + Kernel.sleep 1.5 + # raise Interrupt, nil # let the run loop catch it + run_all_tests + @interrupted = false + end +end diff --git a/sane-defaults.el b/sane-defaults.el index 5e0448f07..4bd24af59 100644 --- a/sane-defaults.el +++ b/sane-defaults.el @@ -42,6 +42,9 @@ ;; Remove text in active region if inserting text (delete-selection-mode 1) +;; Don't highlight matches with jump-char - it's distracting +(setq jump-char-lazy-highlight-face nil) + ;; Always display line and column numbers (setq line-number-mode t) (setq column-number-mode t) @@ -71,6 +74,12 @@ ;; Keep cursor away from edges when scrolling up/down (require 'smooth-scrolling) +;; Allow recursive minibuffers +(setq enable-recursive-minibuffers t) + +;; Don't be so stingy on the memory, we have lots now. It's the distant future. +(setq gc-cons-threshold 20000000) + ;; org-mode: Don't ruin S-arrow to switch windows please (use M-+ and M-- instead to toggle) (setq org-replace-disputed-keys t) diff --git a/setup-clojure-mode.el b/setup-clojure-mode.el index 4c53cf85b..c8ccdc39e 100644 --- a/setup-clojure-mode.el +++ b/setup-clojure-mode.el @@ -1,14 +1,40 @@ (require 'clojure-mode) -(define-key clojure-mode-map (kbd "C-c C-j") 'clj-jump-to-other-file) -(define-key clojure-mode-map (kbd "C-c M-j") 'clj-jump-to-other-file-other-window) - (defadvice clojure-test-run-tests (before save-first activate) (save-buffer)) -(eval-after-load "nrepl" - '(progn - (define-key nrepl-mode-map (kbd "C-,") 'complete-symbol) - (define-key nrepl-interaction-mode-map (kbd "C-,") 'complete-symbol))) +(defadvice nrepl-load-current-buffer (before save-first activate) + (save-buffer)) + +(require 'clj-refactor) + +(cljr-add-keybindings-with-modifier "C-s-") +(define-key clj-refactor-map (kbd "C-x C-r") 'cljr-rename-file) + +(add-hook 'clojure-mode-hook (lambda () (clj-refactor-mode 1))) + +(define-key clojure-mode-map (kbd "s-j") 'clj-jump-to-other-file) + +(require 'nrepl) + +(define-key nrepl-mode-map (kbd "") nil) +(define-key nrepl-mode-map (kbd "C-,") 'complete-symbol) +(define-key nrepl-interaction-mode-map (kbd "C-,") 'complete-symbol) + +;; Configure nrepl.el +(setq nrepl-hide-special-buffers t) +(setq nrepl-popup-stacktraces-in-repl t) +(setq nrepl-history-file "~/.emacs.d/nrepl-history") + +;; Some default eldoc facilities +(add-hook 'nrepl-connected-hook + (defun my-nrepl-eldoc-hook () + (add-hook 'clojure-mode-hook 'turn-on-eldoc-mode) + (add-hook 'nrepl-interaction-mode-hook 'nrepl-turn-on-eldoc-mode) + (nrepl-enable-on-existing-clojure-buffers))) + +;; Setup nrepl-inspect +(require 'nrepl-inspect) +(define-key nrepl-mode-map (kbd "C-c C-i") 'nrepl-inspect) (provide 'setup-clojure-mode) diff --git a/setup-dired.el b/setup-dired.el index 898439fa9..62c0749ee 100644 --- a/setup-dired.el +++ b/setup-dired.el @@ -6,8 +6,12 @@ (setq-default dired-details-hidden-string "--- ") (dired-details-install) +;; Move files between split panes +(setq dired-dwim-target t) + ;; Reload dired after making changes (--each '(dired-do-rename + dired-do-copy dired-create-directory wdired-abort-changes) (eval `(defadvice ,it (after revert-buffer activate) @@ -19,13 +23,13 @@ (backward-char (- (current-column) 2))) (define-key dired-mode-map (kbd "C-a") 'dired-back-to-start-of-files) +(define-key dired-mode-map (kbd "k") 'dired-do-delete) -;; M-up is nicer in dired if it moves to the third line - straight to the ".." +;; M-up is nicer in dired if it moves to the fourth line - the first file (defun dired-back-to-top () (interactive) (beginning-of-buffer) - (next-line 2) - (dired-back-to-start-of-files)) + (dired-next-line 4)) (define-key dired-mode-map (vector 'remap 'beginning-of-buffer) 'dired-back-to-top) (define-key dired-mode-map (vector 'remap 'smart-up) 'dired-back-to-top) @@ -34,8 +38,7 @@ (defun dired-jump-to-bottom () (interactive) (end-of-buffer) - (next-line -1) - (dired-back-to-start-of-files)) + (dired-next-line -1)) (define-key dired-mode-map (vector 'remap 'end-of-buffer) 'dired-jump-to-bottom) (define-key dired-mode-map (vector 'remap 'smart-down) 'dired-jump-to-bottom) diff --git a/setup-ffip.el b/setup-ffip.el index e1dce7e60..7e7758e6e 100644 --- a/setup-ffip.el +++ b/setup-ffip.el @@ -16,8 +16,7 @@ "Given a set of names, will exclude results with those names in the path. Example: -(ffip-local-excludes \"target\" \"overlays\") -" +(ffip-local-excludes \"target\" \"overlays\")" (set (make-local-variable 'ffip-find-options) (ffip--create-exclude-find-options names))) @@ -25,8 +24,7 @@ Example: "An exhaustive list of file name patterns to look for. Example: -(ffip-local-patterns \"*.js\" \"*.jsp\" \"*.css\") -" +(ffip-local-patterns \"*.js\" \"*.jsp\" \"*.css\")" (set (make-local-variable 'ffip-patterns) patterns)) diff --git a/setup-flycheck.el b/setup-flycheck.el new file mode 100644 index 000000000..f7d5d01e2 --- /dev/null +++ b/setup-flycheck.el @@ -0,0 +1,35 @@ +(require 'flycheck) + +(defun magnars/adjust-flycheck-automatic-syntax-eagerness () + "Adjust how often we check for errors based on if there are any. + +This lets us fix any errors as quickly as possible, but in a +clean buffer we're an order of magnitude laxer about checking." + (setq flycheck-idle-change-delay + (if flycheck-current-errors 0.5 5.0))) + +;; Each buffer gets its own idle-change-delay because of the +;; buffer-sensitive adjustment above. +(make-variable-buffer-local 'flycheck-idle-change-delay) + +(add-hook 'flycheck-after-syntax-check-hook + 'magnars/adjust-flycheck-automatic-syntax-eagerness) + +;; Remove newline checks, since they would trigger an immediate check +;; when we want the idle-change-delay to be in effect while editing. +(setq flycheck-check-syntax-automatically '(save + idle-change + mode-enabled)) + +(defun flycheck-handle-idle-change () + "Handle an expired idle time since the last change. + +This is an overwritten version of the original +flycheck-handle-idle-change, which removes the forced deferred. +Timers should only trigger inbetween commands in a single +threaded system and the forced deferred makes errors never show +up before you execute another command." + (flycheck-clear-idle-change-timer) + (flycheck-buffer-automatically 'idle-change)) + +(provide 'setup-flycheck) diff --git a/setup-hippie.el b/setup-hippie.el index de2216feb..4efeb1006 100644 --- a/setup-hippie.el +++ b/setup-hippie.el @@ -158,6 +158,7 @@ string). It returns t if a new completion is found, nil otherwise." (interactive) (let ((hippie-expand-try-functions-list '(try-expand-line-closest-first try-expand-line-all-buffers))) + (end-of-line) (hippie-expand nil))) ;; Don't case-fold when expanding with hippe diff --git a/setup-html-mode.el b/setup-html-mode.el index 88b9affeb..e8fc1a87e 100644 --- a/setup-html-mode.el +++ b/setup-html-mode.el @@ -1,16 +1,16 @@ (defun skip-to-next-blank-line () (interactive) (let ((inhibit-changing-match-data t)) - (forward-char 1) + (skip-syntax-forward " >") (unless (search-forward-regexp "^\\s *$" nil t) - (forward-char -1)))) + (goto-char (point-max))))) (defun skip-to-previous-blank-line () (interactive) (let ((inhibit-changing-match-data t)) - (forward-char -1) + (skip-syntax-backward " >") (unless (search-backward-regexp "^\\s *$" nil t) - (forward-char 1)))) + (goto-char (point-min))))) (defun html-wrap-in-tag (beg end) (interactive "r") @@ -25,56 +25,44 @@ (indent-region beg (+ end 11)) (goto-char (+ beg 4)))) +(defun --setup-simplezen () + (require 'simplezen) + (set (make-local-variable 'yas/fallback-behavior) + '(apply simplezen-expand-or-indent-for-tab))) + +(add-hook 'sgml-mode-hook '--setup-simplezen) + (eval-after-load "sgml-mode" '(progn - (define-key html-mode-map (kbd "C-") 'skip-to-next-blank-line) - (define-key html-mode-map (kbd "C-") 'skip-to-previous-blank-line) + (define-key html-mode-map [remap forward-paragraph] 'skip-to-next-blank-line) + (define-key html-mode-map [remap backward-paragraph] 'skip-to-previous-blank-line) (define-key html-mode-map (kbd "C-c C-w") 'html-wrap-in-tag) + (define-key html-mode-map (kbd "/") nil) ;; no buggy matching of slashes - ;; Don't show buggy matching of slashes - (define-key html-mode-map (kbd "/") nil) + (define-key html-mode-map (kbd "C-c C-d") 'ng-snip-show-docs-at-point) (require 'tagedit) + + ;; paredit lookalikes (define-key html-mode-map (kbd "s-") 'tagedit-forward-slurp-tag) + (define-key html-mode-map (kbd "C-)") 'tagedit-forward-slurp-tag) (define-key html-mode-map (kbd "s-") 'tagedit-forward-barf-tag) - (define-key html-mode-map (kbd "s-k") 'tagedit-kill-attribute) - )) - -(autoload 'zencoding-mode "zencoding-mode") -(autoload 'zencoding-expand-line "zencoding-mode") + (define-key html-mode-map (kbd "C-}") 'tagedit-forward-barf-tag) + (define-key html-mode-map (kbd "M-r") 'tagedit-raise-tag) + (define-key html-mode-map (kbd "s-s") 'tagedit-splice-tag) + (define-key html-mode-map (kbd "M-S") 'tagedit-split-tag) + (define-key html-mode-map (kbd "M-J") 'tagedit-join-tags) + (define-key html-mode-map (kbd "M-?") 'tagedit-convolute-tags) -(defun zencoding-expand-or-indent-for-tab () - (interactive) - (unless (and (memq last-command yas/expand-only-for-last-commands) - (zencoding-expand-yas)) - (indent-for-tab-command))) + (tagedit-add-experimental-features) + (add-hook 'html-mode-hook (lambda () (tagedit-mode 1))) -(defun --setup-zencoding-mode () - (zencoding-mode) - (add-to-list 'zencoding-self-closing-tags "hr") - (set (make-local-variable 'yas/fallback-behavior) - '(apply zencoding-expand-or-indent-for-tab))) - -(add-hook 'sgml-mode-hook '--setup-zencoding-mode) - -(eval-after-load 'zencoding-mode - '(progn - (define-key zencoding-mode-keymap (kbd "C-j") nil) - (define-key zencoding-mode-keymap (kbd "") nil) - (define-key zencoding-mode-keymap (kbd "C-c C-j") 'zencoding-expand-line) - - (defun zencoding-transform-yas (ast) - (let ((zencoding-leaf-function (lambda () "$0"))) - (zencoding-transform ast))) - - (defun zencoding-indent (text) - "Indent the text" - (if text - (replace-regexp-in-string "\n" "\n " (concat "\n" text)) - nil)) - - (diminish 'zencoding-mode) + ;; no paredit equivalents + (define-key html-mode-map (kbd "s-k") 'tagedit-kill-attribute) + (define-key html-mode-map (kbd "s-") 'tagedit-toggle-multiline-tag))) - )) +;; after deleting a tag, indent properly +(defadvice sgml-delete-tag (after reindent activate) + (indent-region (point-min) (point-max))) (provide 'setup-html-mode) diff --git a/setup-ido.el b/setup-ido.el index 0f865093f..3f1d573e7 100644 --- a/setup-ido.el +++ b/setup-ido.el @@ -10,14 +10,40 @@ ido-use-filename-at-point nil ido-max-prospects 10) +;; Try out flx-ido for better flex matching between words +(require 'flx-ido) +(ido-everywhere 1) +(flx-ido-mode 1) +;; disable ido faces to see flx highlights. +(setq ido-use-faces nil) + +;; flx-ido looks better with ido-vertical-mode +(require 'ido-vertical-mode) +(ido-vertical-mode) + +(defun sd/ido-define-keys () ;; C-n/p is more intuitive in vertical layout + (define-key ido-completion-map (kbd "C-n") 'ido-next-match) + (define-key ido-completion-map (kbd "") 'ido-next-match) + (define-key ido-completion-map (kbd "C-p") 'ido-prev-match) + (define-key ido-completion-map (kbd "") 'ido-prev-match)) + (add-hook 'ido-setup-hook (lambda () + ;; Go straight home + (define-key ido-file-completion-map + (kbd "~") + (lambda () + (interactive) + (cond + ((looking-back "~/") (insert "projects/")) + ((looking-back "/") (insert "~/")) + (:else (call-interactively 'self-insert-command))))) - ;; Use C-w to go back up a dir to better match normal usage of C-w - ;; - insert current file name with C-x C-w instead. - (define-key ido-file-completion-map (kbd "C-w") 'ido-delete-backward-updir) - (define-key ido-file-completion-map (kbd "C-x C-w") 'ido-copy-current-file-name))) + ;; Use C-w to go back up a dir to better match normal usage of C-w + ;; - insert current file name with C-x C-w instead. + (define-key ido-file-completion-map (kbd "C-w") 'ido-delete-backward-updir) + (define-key ido-file-completion-map (kbd "C-x C-w") 'ido-copy-current-file-name))) ;; Always rescan buffer for imenu (set-default 'imenu-auto-rescan t) diff --git a/setup-js2-mode.el b/setup-js2-mode.el index b18d6453a..1635684ed 100644 --- a/setup-js2-mode.el +++ b/setup-js2-mode.el @@ -1,3 +1,5 @@ +;;; setup-js2-mode.el --- tweak js2 settings -*- lexical-binding: t; -*- + (setq-default js2-allow-rhino-new-expr-initializer nil) (setq-default js2-auto-indent-p nil) (setq-default js2-enter-indents-newline nil) @@ -7,17 +9,102 @@ (setq-default js2-mirror-mode nil) (setq-default js2-strict-inconsistent-return-warning nil) (setq-default js2-auto-indent-p t) -(setq-default js2-rebind-eol-bol-keys nil) (setq-default js2-include-rhino-externs nil) (setq-default js2-include-gears-externs nil) (setq-default js2-concat-multiline-strings 'eol) +(setq-default js2-rebind-eol-bol-keys nil) + +;; Let flycheck handle parse errors +(setq-default js2-show-parse-errors nil) +(setq-default js2-strict-missing-semi-warning nil) +(setq-default js2-strict-trailing-comma-warning t) ;; jshint does not warn about this now for some reason + +(add-hook 'js2-mode-hook (lambda () (flycheck-mode 1))) (require 'js2-mode) (require 'js2-refactor) +(js2r-add-keybindings-with-prefix "C-c C-m") (require 'js2-imenu-extras) (js2-imenu-extras-setup) +;; Set up wrapping of pairs, with the possiblity of semicolons thrown into the mix + +(defun js2r--setup-wrapping-pair (open close semicolonp) + (define-key js2-mode-map (kbd open) (λ (js2r--self-insert-wrapping open close semicolonp))) + (unless (s-equals? open close) + (define-key js2-mode-map (kbd close) (λ (js2r--self-insert-closing open close))))) + +(define-key js2-mode-map (kbd ";") + (λ (if (looking-at ";") + (forward-char) + (funcall 'self-insert-command 1)))) + +(defun js2r--self-insert-wrapping (open close semicolonp) + (cond + ((use-region-p) + (save-excursion + (let ((beg (region-beginning)) + (end (region-end))) + (goto-char end) + (insert close) + (goto-char beg) + (insert open)))) + + ((and (s-equals? open close) + (looking-back (regexp-quote open)) + (looking-at (regexp-quote close))) + (forward-char (length close))) + + ((js2-mode-inside-comment-or-string) + (funcall 'self-insert-command 1)) + + (:else + (let ((end (js2r--something-to-close-statement))) + (insert open close end) + (backward-char (+ (length close) (length end))) + (js2r--remove-all-this-cruft-on-backward-delete))))) + +(defun js2r--remove-all-this-cruft-on-backward-delete () + (set-temporary-overlay-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "DEL") 'undo-tree-undo) + (define-key map (kbd "C-h") 'undo-tree-undo) + map) nil)) + +(defun js2r--self-insert-closing (open close) + (if (and (looking-back (regexp-quote open)) + (looking-at (regexp-quote close))) + (forward-char (length close)) + (funcall 'self-insert-command 1))) + +(defun js2r--does-not-need-semi () + (save-excursion + (back-to-indentation) + (or (looking-at "if ") + (looking-at "function ") + (looking-at "for ") + (looking-at "while ") + (looking-at "try ") + (looking-at "} else ")))) + +(defun js2r--something-to-close-statement () + (cond + ((not (eolp)) "") + ((js2-object-prop-node-p (js2-node-at-point)) ",") + ((js2r--does-not-need-semi) "") + (:else ";"))) + +(js2r--setup-wrapping-pair "(" ")" 'js2r--needs-semi) +(js2r--setup-wrapping-pair "{" "}" 'js2r--needs-semi) +(js2r--setup-wrapping-pair "[" "]" 'eolp) +(js2r--setup-wrapping-pair "\"" "\"" 'eolp) +(js2r--setup-wrapping-pair "'" "'" 'eolp) + +;; no semicolon inside object literals + +;; + (define-key js2-mode-map (kbd "C-c RET jt") 'jump-to-test-file) (define-key js2-mode-map (kbd "C-c RET ot") 'jump-to-test-file-other-window) (define-key js2-mode-map (kbd "C-c RET js") 'jump-to-source-file) @@ -25,6 +112,8 @@ (define-key js2-mode-map (kbd "C-c RET jo") 'jump-between-source-and-test-files) (define-key js2-mode-map (kbd "C-c RET oo") 'jump-between-source-and-test-files-other-window) +(define-key js2-mode-map (kbd "C-c RET dp") 'js2r-duplicate-object-property-node) + (define-key js2-mode-map (kbd "C-c RET ta") 'toggle-assert-refute) (defadvice js2r-inline-var (after reindent-buffer activate) @@ -51,9 +140,6 @@ (define-key js2-mode-map (kbd "TAB") 'js2-tab-properly) -;; Don't redefine C-a for me please, js2-mode -(define-key js2-mode-map (kbd "C-a") nil) - ;; When renaming/deleting js-files, check for corresponding testfile (define-key js2-mode-map (kbd "C-x C-r") 'js2r-rename-current-buffer-file) (define-key js2-mode-map (kbd "C-x C-k") 'js2r-delete-current-buffer-file) @@ -89,6 +175,38 @@ " *, *" t)) )))) +(require 'json) + +;; Tern.JS +(add-to-list 'load-path (expand-file-name "tern/emacs" site-lisp-dir)) +(autoload 'tern-mode "tern.el" nil t) +;;(add-hook 'js2-mode-hook (lambda () (tern-mode t))) +(eval-after-load 'auto-complete + '(eval-after-load 'tern + '(progn + (require 'tern-auto-complete) + (tern-ac-setup)))) + + +(defun my-aget (key map) + (cdr (assoc key map))) + +(defun js2-fetch-autolint-externs (file) + (let* ((settings (with-temp-buffer + (insert-file-literally file) + (javascript-mode) + (let (kill-ring) (kill-comment 1000)) + (->> (buffer-substring (point-min) (point-max)) + (s-trim) + (s-chop-prefix "module.exports = ") + (s-chop-suffix ";") + (json-read-from-string)))) + (predef (->> settings + (my-aget 'linterOptions) + (my-aget 'predef)))) + (--each (append predef nil) + (add-to-list 'js2-additional-externs it)))) + (defun cjsp--eldoc-innards (beg) (save-excursion (goto-char beg) diff --git a/setup-magit.el b/setup-magit.el index b4336ead6..b4363f3e6 100644 --- a/setup-magit.el +++ b/setup-magit.el @@ -2,10 +2,21 @@ ;; Subtler highlight (set-face-background 'magit-item-highlight "#121212") +(set-face-background 'diff-file-header "#121212") (set-face-foreground 'diff-context "#666666") (set-face-foreground 'diff-added "#00cc33") (set-face-foreground 'diff-removed "#ff0000") +;; todo: +;; diff-added-face diff-changed-face +;; diff-context-face diff-file-header-face +;; diff-function-face diff-header-face +;; diff-hunk-header-face diff-index-face +;; diff-indicator-added-face diff-indicator-changed-face +;; diff-indicator-removed-face diff-nonexistent-face +;; diff-removed-face + + ;; Load git configurations ;; For instance, to run magit-svn-mode in a project, do: ;; @@ -76,5 +87,9 @@ (define-key magit-status-mode-map (kbd "W") 'magit-toggle-whitespace) +;; Show blame for current line + +(require-package 'git-messenger) +(global-set-key (kbd "C-x v p") #'git-messenger:popup-message) (provide 'setup-magit) diff --git a/setup-org.el b/setup-org.el index 77c26ce0f..91b7ee072 100644 --- a/setup-org.el +++ b/setup-org.el @@ -3,8 +3,9 @@ (defun myorg-update-parent-cookie () (when (equal major-mode 'org-mode) (save-excursion - (org-back-to-heading) - (org-update-parent-todo-statistics)))) + (ignore-errors + (org-back-to-heading) + (org-update-parent-todo-statistics))))) (defadvice org-kill-line (after fix-cookies activate) (myorg-update-parent-cookie)) diff --git a/setup-package.el b/setup-package.el index 9e89e9f03..a002e642a 100644 --- a/setup-package.el +++ b/setup-package.el @@ -1,30 +1,32 @@ (require 'package) +(require 'dash) -(defvar marmalade '("marmalade" . "http://marmalade-repo.org/packages/")) -(defvar gnu '("gnu" . "http://elpa.gnu.org/packages/")) -(defvar melpa '("melpa" . "http://melpa.milkbox.net/packages/")) - -;; Add marmalade to package repos -(add-to-list 'package-archives marmalade) -(add-to-list 'package-archives melpa t) +;; Add melpa to package repos +(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t) (package-initialize) -(unless (and (file-exists-p "~/.emacs.d/elpa/archives/marmalade") - (file-exists-p "~/.emacs.d/elpa/archives/gnu") - (file-exists-p "~/.emacs.d/elpa/archives/melpa")) +(unless (file-exists-p "~/.emacs.d/elpa/archives/melpa") (package-refresh-contents)) -(defun packages-install (&rest packages) - (mapc (lambda (package) - (let ((name (car package)) - (repo (cdr package))) - (when (not (package-installed-p name)) - (let ((package-archives (list repo))) - (package-initialize) - (package-install name))))) - packages) - (package-initialize) +(defun packages-install (packages) + (--each packages + (when (not (package-installed-p it)) + (package-install it))) (delete-other-windows)) +;;; On-demand installation of packages + +(defun require-package (package &optional min-version no-refresh) + "Install given PACKAGE, optionally requiring MIN-VERSION. +If NO-REFRESH is non-nil, the available package lists will not be +re-downloaded in order to locate PACKAGE." + (if (package-installed-p package min-version) + t + (if (or (assoc package package-archive-contents) no-refresh) + (package-install package) + (progn + (package-refresh-contents) + (require-package package min-version t))))) + (provide 'setup-package) diff --git a/setup-paredit.el b/setup-paredit.el index 95184b604..aabba46dc 100644 --- a/setup-paredit.el +++ b/setup-paredit.el @@ -1,6 +1,8 @@ ;; My keybindings for paredit (require 'paredit) +(require 'dash) +(require 's) (defun paredit-wrap-round-from-behind () (interactive) @@ -9,18 +11,81 @@ (insert " ") (forward-char -1)) -(defun setup-paredit-for-mode-map (mode-map) - (define-key mode-map (kbd "s-") 'paredit-raise-sexp) - (define-key mode-map (kbd "s-") 'paredit-forward-slurp-sexp) - (define-key mode-map (kbd "s-") 'paredit-forward-barf-sexp) - (define-key mode-map (kbd "s-S-") 'paredit-backward-slurp-sexp) - (define-key mode-map (kbd "s-S-") 'paredit-backward-barf-sexp) - (define-key mode-map (kbd "s-8") 'paredit-wrap-round) - (define-key mode-map (kbd "s-9") 'paredit-wrap-round-from-behind) - (define-key mode-map (kbd "s-") 'paredit-splice-sexp-killing-backward) - (define-key mode-map (kbd "s-t") 'transpose-sexps)) - -(eval-after-load "lisp-mode" '(setup-paredit-for-mode-map emacs-lisp-mode-map)) -(eval-after-load "clojure-mode" '(setup-paredit-for-mode-map clojure-mode-map)) +(defun paredit-wrap-square-from-behind () + (interactive) + (forward-sexp -1) + (paredit-wrap-square)) + +(defun paredit-wrap-curly-from-behind () + (interactive) + (forward-sexp -1) + (paredit-wrap-curly)) + +(defun paredit-kill-region-or-backward-word () + (interactive) + (if (region-active-p) + (kill-region (region-beginning) (region-end)) + (paredit-backward-kill-word))) + +(add-hook 'clojure-mode-hook (lambda () (paredit-mode 1))) +(add-hook 'nrepl-mode-hook (lambda () (paredit-mode 1))) +(add-hook 'emacs-lisp-mode-hook (lambda () (paredit-mode 1))) + +(define-key paredit-mode-map (kbd "M-(") 'paredit-wrap-round) +(define-key paredit-mode-map (kbd "M-)") 'paredit-wrap-round-from-behind) +(define-key paredit-mode-map (kbd "M-s-8") 'paredit-wrap-square) +(define-key paredit-mode-map (kbd "M-s-9") 'paredit-wrap-square-from-behind) +(define-key paredit-mode-map (kbd "M-s-(") 'paredit-wrap-curly) +(define-key paredit-mode-map (kbd "M-s-)") 'paredit-wrap-curly-from-behind) + +(define-key paredit-mode-map (kbd "C-w") 'paredit-kill-region-or-backward-word) + +;; Change nasty paredit keybindings +(defvar my-nasty-paredit-keybindings-remappings + '(("M-s" "s-s" paredit-splice-sexp) + ("M-" "s-" paredit-splice-sexp-killing-backward) + ("M-" "s-" paredit-splice-sexp-killing-forward) + ("C-" "s-" paredit-forward-slurp-sexp) + ("C-" "s-" paredit-forward-barf-sexp) + ("C-M-" "s-S-" paredit-backward-slurp-sexp) + ("C-M-" "s-S-" paredit-backward-barf-sexp))) + +(define-key paredit-mode-map (kbd "s-r") 'paredit-raise-sexp) + +(--each my-nasty-paredit-keybindings-remappings + (let ((original (car it)) + (replacement (cadr it)) + (command (car (last it)))) + (define-key paredit-mode-map (read-kbd-macro original) nil) + (define-key paredit-mode-map (read-kbd-macro replacement) command))) + +;; don't hijack \ please +(define-key paredit-mode-map (kbd "\\") nil) + +;; Enable `paredit-mode' in the minibuffer, during `eval-expression'. +(defun conditionally-enable-paredit-mode () + (if (eq this-command 'eval-expression) + (paredit-mode 1))) + +(add-hook 'minibuffer-setup-hook 'conditionally-enable-paredit-mode) + +;; making paredit work with delete-selection-mode +(put 'paredit-forward-delete 'delete-selection 'supersede) +(put 'paredit-backward-delete 'delete-selection 'supersede) +(put 'paredit-newline 'delete-selection t) + +;; functions in smartparens that do not have an equivalent in paredit - take a look at them +(when nil + '(sp-beginning-of-sexp + sp-end-of-sexp + sp-next-sexp + sp-previous-sexp + sp-kill-sexp + sp-unwrap-sexp + sp-backward-unwrap-sexp + sp-select-next-thing-exchange + sp-select-next-thing + sp-forward-symbol + sp-backward-symbol)) (provide 'setup-paredit) diff --git a/setup-rgrep.el b/setup-rgrep.el index 91341d1b8..f15584502 100644 --- a/setup-rgrep.el +++ b/setup-rgrep.el @@ -77,4 +77,44 @@ ;; Use same keybinding as occur (setq wgrep-enable-key "e"))) +;; Command to add cursor to all matches in wgrep + +(require 'dash) + +(defvar grep-match-positions nil) +(make-variable-buffer-local 'grep-match-positions) + +(defun grep-register-match-positions () + (save-excursion + (forward-line 0) + (let ((end (point)) beg) + (goto-char compilation-filter-start) + (forward-line 0) + (setq beg (point)) + ;; Only operate on whole lines so we don't get caught with part of an + ;; escape sequence in one chunk and the rest in another. + (when (< (point) end) + (setq end (copy-marker end)) + ;; Register all positions of matches + (while (re-search-forward "\033\\[0?1;31m\\(.*?\\)\033\\[[0-9]*m" end 1) + (add-to-list 'grep-match-positions (set-marker (make-marker) (match-beginning 1)))))))) + +(eval-after-load "grep" + '(defadvice grep-mode (after grep-register-match-positions activate) + (add-hook 'compilation-filter-hook 'grep-register-match-positions nil t))) + +(defun mc/add-cursors-to-all-matches () + (interactive) + (--each grep-match-positions + (unless (= 0 it-index) + (mc/create-fake-cursor-at-point)) + (goto-char it)) + (mc/maybe-multiple-cursors-mode)) + +(eval-after-load "multiple-cursors" + '(add-to-list 'mc--default-cmds-to-run-once 'mc/add-cursors-to-all-matches)) + +(eval-after-load "wgrep" + '(define-key wgrep-mode-map (kbd "C-c C-æ") 'mc/add-cursors-to-all-matches)) + (provide 'setup-rgrep) diff --git a/setup-ruby-mode.el b/setup-ruby-mode.el index dcd073cf1..48d6e43be 100644 --- a/setup-ruby-mode.el +++ b/setup-ruby-mode.el @@ -1,3 +1,6 @@ +;; avoid ridiculous ruby indentation +(setq ruby-deep-indent-paren nil) + (defun ruby--jump-to-test () (find-file (replace-regexp-in-string diff --git a/setup-skewer.el b/setup-skewer.el new file mode 100644 index 000000000..539405052 --- /dev/null +++ b/setup-skewer.el @@ -0,0 +1,29 @@ + +;; Bookmarklet to load skewer: +;; +;; javascript:(function(){var d=document ;var s=d.createElement('script');s.src='http://localhost:8023/skewer';d.body.appendChild(s);})() +;; + +(require 'skewer-mode) +(require 'skewer-repl) +(require 'skewer-html) +(require 'skewer-css) + +(defun skewer-start () + (interactive) + (let ((httpd-port 8023)) + (httpd-start) + (message "Ready to skewer the browser. Now jack in with the bookmarklet."))) + +(defun skewer-demo () + (interactive) + (let ((httpd-port 8024)) + (run-skewer) + (skewer-repl))) + +(require 'mouse-slider-mode) + +(add-to-list 'mouse-slider-mode-eval-funcs + '(js2-mode . skewer-eval-defun)) + +(provide 'setup-skewer) diff --git a/setup-slime-js.el b/setup-slime-js.el deleted file mode 100644 index 6efa61e39..000000000 --- a/setup-slime-js.el +++ /dev/null @@ -1,121 +0,0 @@ -;; Set up slime-js -;; -;; To install, see https://github.com/swank-js/swank-js/wiki/Installation -;; -;; This is what I did: -;; -;; npm install swank-js -g -;; M-x package-install slime-js -;; -;; The slime-js version in marmalade requires swank 2010.04.04, or at least -;; one prior to the breaking change in 2011. -;; -;; It also requires js2-mode, which is a good choice in either case. I highly -;; recommend this fork: -;; -;; https://github.com/mooz/js2-mode -;; -;; My settings found in this file also requires js2-refactor: -;; -;; https://github.com/magnars/js2-refactor.el -;; -;; I have included this file in init.el like so: -;; -;; (add-hook 'after-init-hook -;; #'(lambda () -;; (when (locate-library "slime-js") -;; (require 'setup-slime-js)))) -;; - -(require 'slime) -(require 'slime-js) -(require 'js2-refactor) - -(set-default 'slime-js-target-url "http://localhost:3000") -(set-default 'slime-js-connect-url "http://localhost:8009") -(set-default 'slime-js-starting-url "/") -(set-default 'slime-js-swank-command "swank-js") -(set-default 'slime-js-swank-args '()) -(set-default 'slime-js-browser-command "open -a \"Google Chrome\"") -(set-default 'slime-js-browser-jacked-in-p nil) - -(add-hook 'js2-mode-hook (lambda () (slime-js-minor-mode 1))) - -(defun slime-js-run-swank () - "Runs the swank side of the equation." - (interactive) - (apply #'make-comint "swank-js" slime-js-swank-command nil slime-js-swank-args)) - -(defun slime-js-jack-in-node () - "Start a swank-js server and connect to it, opening a repl." - (interactive) - (slime-js-run-swank) - (sleep-for 1) - (setq slime-protocol-version 'ignore) - (slime-connect "localhost" 4005)) - -(defun slime-js-jack-in-browser () - "Start a swank-js server, connect to it, open a repl, open a browser, connect to that." - (interactive) - (slime-js-jack-in-node) - (sleep-for 2) - (slime-js-set-target-url slime-js-target-url) - (shell-command (concat slime-js-browser-command " " slime-js-connect-url slime-js-starting-url)) - (sleep-for 3) - (setq slime-remote-history nil) - (slime-js-sticky-select-remote (caadr (slime-eval '(js:list-remotes)))) - (setq slime-js-browser-jacked-in-p t) - (global-set-key [f5] 'slime-js-reload)) - -(defadvice save-buffer (after save-css-buffer activate) - (when (and slime-js-browser-jacked-in-p (eq major-mode 'css-mode)) - (slime-js-refresh-css))) - -(defun js2-eval-friendly-node-p (n) - (or (and (js2-stmt-node-p n) (not (js2-block-node-p n))) - (and (js2-function-node-p n) (js2-function-node-name n)))) - -(defun slime-js--echo-result (result &rest _) - (message result)) - -(defun slime-js--replace-with-result (replacement beg end) - (save-excursion - (goto-char beg) - (delete-char (- end beg)) - (insert replacement))) - -(defun slime-js-eval-region (beg end &optional func) - (lexical-let ((func (or func 'slime-js--echo-result)) - (beg beg) - (end end)) - (slime-flash-region beg end) - (slime-js-eval - (buffer-substring-no-properties beg end) - #'(lambda (s) (funcall func (cadr s) beg end))))) - -(defun slime-js-eval-statement (&optional func) - (let ((node (js2r--closest 'js2-eval-friendly-node-p))) - (slime-js-eval-region (js2-node-abs-pos node) - (js2-node-abs-end node) - func))) - -(defun slime-js-eval-current () - (interactive) - (if (use-region-p) - (slime-js-eval-region (point) (mark)) - (slime-js-eval-statement))) - -(defun slime-js-eval-and-replace-current () - (interactive) - (if (use-region-p) - (slime-js-eval-region (point) (mark) 'slime-js--replace-with-result) - (slime-js-eval-statement 'slime-js--replace-with-result))) - -(define-key slime-js-minor-mode-map (kbd "C-x C-e") 'slime-js-eval-current) -(define-key slime-js-minor-mode-map (kbd "C-c C-e") 'slime-js-eval-and-replace-current) - -;; Remove slime-minor-mode from mode line if diminish.el is installed -(when (boundp 'diminish) - (diminish 'slime-js-minor-mode)) - -(provide 'setup-slime-js) diff --git a/setup-yasnippet.el b/setup-yasnippet.el index e3981a87a..be35a9f56 100644 --- a/setup-yasnippet.el +++ b/setup-yasnippet.el @@ -4,29 +4,21 @@ (setq yas/snippet-dirs '("~/.emacs.d/snippets")) (yas/global-mode 1) -;; Include snippets for Buster.js +;; Include snippets for stuff (require 'buster-snippets) +(require 'angular-snippets) +(require 'datomic-snippets) ;; Jump to end of snippet definition (define-key yas/keymap (kbd "") 'yas/exit-all-snippets) -;; Don't expand yasnippets in every setting -(setq yas/expand-only-for-last-commands - '( - self-insert-command - yas/exit-all-snippets - yas/abort-snippet - yas/skip-and-clear-or-delete-char - yas/next-field-or-maybe-expand - )) - ;; Inter-field navigation (defun yas/goto-end-of-active-field () (interactive) (let* ((snippet (car (yas/snippets-at-point))) (position (yas/field-end (yas/snippet-active-field snippet)))) (if (= (point) position) - (move-end-of-line) + (move-end-of-line 1) (goto-char position)))) (defun yas/goto-start-of-active-field () @@ -34,7 +26,7 @@ (let* ((snippet (car (yas/snippets-at-point))) (position (yas/field-start (yas/snippet-active-field snippet)))) (if (= (point) position) - (move-beginning-of-line) + (move-beginning-of-line 1) (goto-char position)))) (define-key yas/keymap (kbd "C-e") 'yas/goto-end-of-active-field) @@ -43,6 +35,9 @@ ;; No dropdowns please, yas (setq yas/prompt-functions '(yas/ido-prompt yas/completing-prompt)) +;; No need to be so verbose +(setq yas/verbosity 1) + ;; Wrap around region (setq yas/wrap-around-region t) diff --git a/site-lisp/angular-snippets b/site-lisp/angular-snippets new file mode 160000 index 000000000..f67cfea80 --- /dev/null +++ b/site-lisp/angular-snippets @@ -0,0 +1 @@ +Subproject commit f67cfea80cccc1901f0559c8517cf40d1f55068a diff --git a/site-lisp/buster-snippets b/site-lisp/buster-snippets index eca1947e7..14cc3bfd7 160000 --- a/site-lisp/buster-snippets +++ b/site-lisp/buster-snippets @@ -1 +1 @@ -Subproject commit eca1947e715e2a807a894e7c5e85bde07c779daa +Subproject commit 14cc3bfd741840fa9c244a5e79f38f73b8322940 diff --git a/site-lisp/change-inner b/site-lisp/change-inner index e18aca443..6374b745e 160000 --- a/site-lisp/change-inner +++ b/site-lisp/change-inner @@ -1 +1 @@ -Subproject commit e18aca44328b7e8790803af6f22482bc068e6813 +Subproject commit 6374b745ee1fd0302ad8596cdb7aca1bef33a730 diff --git a/site-lisp/clj-refactor b/site-lisp/clj-refactor new file mode 160000 index 000000000..d874f11d6 --- /dev/null +++ b/site-lisp/clj-refactor @@ -0,0 +1 @@ +Subproject commit d874f11d61ee8e16b107b63625b5dcdda88b684b diff --git a/site-lisp/coffee-mode b/site-lisp/coffee-mode deleted file mode 160000 index 244d4b3d1..000000000 --- a/site-lisp/coffee-mode +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 244d4b3d16487f0f6bf1235b343ff4483c0e2983 diff --git a/site-lisp/dash b/site-lisp/dash index 5e72ff9c5..2b200884c 160000 --- a/site-lisp/dash +++ b/site-lisp/dash @@ -1 +1 @@ -Subproject commit 5e72ff9c51e0d7120b036a52cc4c20c50e207644 +Subproject commit 2b200884cacd6856f52ccbea8fd3aee41856e8cd diff --git a/site-lisp/datomic-snippets b/site-lisp/datomic-snippets new file mode 160000 index 000000000..7116eac8e --- /dev/null +++ b/site-lisp/datomic-snippets @@ -0,0 +1 @@ +Subproject commit 7116eac8e15a16fc72973b96fa855fd9784bbbb8 diff --git a/site-lisp/expand-region b/site-lisp/expand-region index 3465ae7ee..3cf560c29 160000 --- a/site-lisp/expand-region +++ b/site-lisp/expand-region @@ -1 +1 @@ -Subproject commit 3465ae7ee6f3f7637d2cd5e24c0cf43c43a3fbcf +Subproject commit 3cf560c29559fc8075021dec05ddd7896e76651b diff --git a/site-lisp/flx b/site-lisp/flx new file mode 160000 index 000000000..222f60d28 --- /dev/null +++ b/site-lisp/flx @@ -0,0 +1 @@ +Subproject commit 222f60d28ea03433ded06f4783c6e0e12eebb3b5 diff --git a/site-lisp/flycheck b/site-lisp/flycheck new file mode 160000 index 000000000..c7a260061 --- /dev/null +++ b/site-lisp/flycheck @@ -0,0 +1 @@ +Subproject commit c7a26006138f8819aec1d0f7d629d257fa7fedb4 diff --git a/site-lisp/js2-refactor b/site-lisp/js2-refactor index 8af7835b5..828615e37 160000 --- a/site-lisp/js2-refactor +++ b/site-lisp/js2-refactor @@ -1 +1 @@ -Subproject commit 8af7835b53cbe90dc2ae22db9d2657674162acbe +Subproject commit 828615e37f10cb3ca809a552f0e48cd5e545932b diff --git a/site-lisp/mark-multiple b/site-lisp/mark-multiple deleted file mode 160000 index 23d684160..000000000 --- a/site-lisp/mark-multiple +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 23d684160dd24201ad0a1147478b984df1b238ca diff --git a/site-lisp/mouse-slider-mode.el b/site-lisp/mouse-slider-mode.el new file mode 100644 index 000000000..6aa798466 --- /dev/null +++ b/site-lisp/mouse-slider-mode.el @@ -0,0 +1,110 @@ +;;; mouse-slider-mode.el --- scale numbers dragged under the mouse + +;; This is free and unencumbered software released into the public domain. + +;;; Commentary: + +;; With this minor mode enabled in a buffer, right-clicking and +;; dragging horizontally with the mouse on any number will +;; increase/decrease it. It's works like this (video is not actually +;; about this minor mode): + +;; http://youtu.be/FpxIfCHKGpQ + +;; If an evaluation function is defined for the current major mode in +;; `mouse-slider-mode-eval-funcs', the local expression will also be +;; evaluated as the number is updated. For example, to add support for +;; [Skewer](https://github.com/skeeto/skewer-mode) in +;; [js2-mode](https://github.com/mooz/js2-mode), + +;; (add-to-list 'mouse-slider-mode-eval-funcs +;; '(js2-mode . skewer-eval-defun)) + +;; The variable `mouse-slider-eval' enables/disables this evaluation +;; step. + +;;; Code: + +(require 'cl) +(require 'thingatpt) + +(defvar mouse-slider-scale 1500 + "Rate at which numbers scale. Smaller means faster.") + +(defvar mouse-slider-mode-eval-funcs + `((emacs-lisp-mode . ,(apply-partially #'eval-defun nil))) + "Alist of evaluation functions to run after scaling numbers in +various major modes.") + +(defvar-local mouse-slider-eval t + "When true, run the evaluation function listed in +`mouse-slider-mode-eval-funcs' after updating numbers.") + +(defvar mouse-slider-mode-map + (let ((map (make-sparse-keymap))) + (prog1 map + (define-key map (kbd "") 'mouse-slider-slide))) + "Keymap for mouse-slider-mode.") + +(define-minor-mode mouse-slider-mode + "Scales numbers when they are right-click dragged over." + :keymap mouse-slider-mode-map + :lighter " MSlider") + +(defvar mouse-slider-number-regexp + "[-+]?[0-9]*\\.?[0-9]+\\([eE][-+]?[0-9]+\\)?" + "Regular expression used to match numbers.") + +(defun mouse-slider-number-bounds () + "Return the bounds of the number at point." + (save-excursion + (while (and (not (bobp)) (looking-at-p mouse-slider-number-regexp)) + (backward-char 1)) + (unless (bobp) (forward-char 1)) + (let ((start (point))) + (re-search-forward mouse-slider-number-regexp) + (cons start (point))))) + +(defun* mouse-slider-replace-number (value) + "Replace the number at point with VALUE." + (save-excursion + (let ((region (mouse-slider-number-bounds))) + (delete-region (car region) (cdr region)) + (goto-char (car region)) + (insert (format "%s" value))))) + +(defun mouse-slider-round (value decimals) + "Round VALUE to DECIMALS decimal places." + (let ((n (expt 10 decimals))) + (/ (round (* value n)) 1.0 n))) + +(defun mouse-slider-scale (base pixels) + "Scale BASE by a drag distance of PIXELS." + (expt base (1+ (/ pixels 1.0 mouse-slider-scale)))) + +(defun mouse-slider-slide (event) + "Handle a mouse slider event by continuously updating the +number where the mouse drag began." + (interactive "e") + (save-excursion + (goto-char (posn-point (second event))) + (let ((base (thing-at-point 'number))) + (when base + (flet ((x (event) (car (posn-x-y (second event))))) + (track-mouse + (loop for movement = (read-event) + while (mouse-movement-p movement) + ;; Replace + for diff = (- (x movement) (x event)) + for value = (mouse-slider-scale base diff) + when (not (zerop (x movement))) + do (mouse-slider-replace-number + (mouse-slider-round value 2)) + ;; Eval + for f = (cdr (assoc major-mode mouse-slider-mode-eval-funcs)) + when (and f mouse-slider-eval) + do (funcall f)))))))) + +(provide 'mouse-slider-mode) + +;;; mouse-slider-mode.el ends here diff --git a/site-lisp/multiple-cursors b/site-lisp/multiple-cursors index bfb293f20..6cff0c2eb 160000 --- a/site-lisp/multiple-cursors +++ b/site-lisp/multiple-cursors @@ -1 +1 @@ -Subproject commit bfb293f2001a41dc3d6593c88c1918ceaaea2f7b +Subproject commit 6cff0c2ebdf40f907c7810c0df7d0d0afbd5487b diff --git a/site-lisp/oppdrag-mode.el b/site-lisp/oppdrag-mode.el index 56f8a059f..c3802c585 100644 --- a/site-lisp/oppdrag-mode.el +++ b/site-lisp/oppdrag-mode.el @@ -45,7 +45,7 @@ in an exploded war, re-deploy the file." (defun oppdrag--setup-js-quirks () (when (string-match-p "oppdrag-services" (buffer-file-name)) (fci-mode 1) - (setq js2-additional-externs '("FINN" "testCase" "cull")) + (setq js2-additional-externs '("FINN" "testCase" "cull" "dome" "bane")) (setq js2r-path-to-tests "/test/javascript/tests/") (setq js2r-path-to-sources "/main/webapp/oppdrag/scripts/") (setq js2r-test-suffix "Test") @@ -64,99 +64,5 @@ in an exploded war, re-deploy the file." (add-hook 'js2-mode-hook 'oppdrag--setup-js-quirks) -(defun strapon-transform-mod () - (interactive) - (save-excursion - (let (internal extra-bg beg) - (end-of-line) - (search-backward "class=\"mod") - (search-forward "mod mod") - (setq internal (looking-at "_2nd")) - (setq extra-bg (cond - ((looking-at "_3rd") " bg-pale-blue") - ((looking-at "Att") " bg-pissyellow") - ((looking-at "Tip") " bg-snotgreen") - ((looking-at "Admin") " bg-firm contrast") - ((looking-at "Neutral") " bg-lt-gray") - (t ""))) - (er/mark-symbol) - (delete-region (region-beginning) (region-end)) - (delete-char -1) - (when internal - (insert " internal")) - (setq beg (point)) - (search-forward ">") - (er/mark-inner-tag) - (kill-region (region-beginning) (region-end)) - (newline) - (insert "
") - (yank) - (insert "
") - (newline) - (indent-region beg (1+ (point)))))) - -(defun strapon-transform-request-mapping () - (interactive) - (save-excursion - (let (method-name method-signature beg) - (end-of-line) - - (search-backward "@RequestMapping") - (forward-line 1) - (search-forward "(") - (er/mark-inside-pairs) - (setq method-signature - (let (case-fold-search) - (--> (buffer-substring (region-beginning) (region-end)) - (split-string it "\\s ") - (--select (s-matches? "^[a-z]" it) it) - (--reject (s-matches? "long" it) it) - (s-join " " it) - (s-collapse-whitespace it)))) - (deactivate-mark) - - (forward-char -1) - (er/mark-symbol) - (setq method-name (buffer-substring (region-beginning) (region-end))) - (deactivate-mark) - - (search-backward "@RequestMapping") - (setq beg (point)) - (search-forward "{") - (while (er--point-inside-string-p) - (search-forward "{")) - (copy-region-as-kill beg (point)) - (goto-char beg) - - (new-line-above) - (new-line-above) - (let ((p (point))) - (yank) - - (insert " - model.addAttribute(\"strappedOn\", true); - return " method-name "(" method-signature ") + \"-strapon\"; - }") - - (search-backward "@RequestMapping") - (search-forward "\.") - (replace-match "-strapon.") - - (forward-line 1) - (search-forward "(") - (replace-match "Strapon(") - (search-forward "@RequestMapping") - (indent-region p (point)))))) - -(defun strapon-create-strapon-jsp () - (interactive) - (write-file - (s-replace ".jsp" "-strapon.jsp" (buffer-file-name)) - t)) - -(f6 (strapon-transform-mod)) -(f7 (strapon-transform-request-mapping)) -(f12 (strapon-create-strapon-jsp)) - (provide 'oppdrag-mode) ;;; oppdrag-mode.el ends here diff --git a/site-lisp/project-archetypes/project-archetypes.el b/site-lisp/project-archetypes/project-archetypes.el new file mode 100644 index 000000000..950ef1a84 --- /dev/null +++ b/site-lisp/project-archetypes/project-archetypes.el @@ -0,0 +1,78 @@ +(require 'dash) +(require 's) + +(defvar pa-project-archetypes nil + "The list of available project archetypes.") + +(defvar pa-folder (expand-file-name "project-archetypes" user-emacs-directory) + "The directory containing project archetypes.") + +(defvar pa-project-folder (expand-file-name "projects" "~") + "The directory where projects should be created.") + +(defvar pa-out "*project-archetypes-output*" + "Name of the buffer where output from the running process is displayed.") + +(defun pa-declare-project-archetype (name fn) + "Add project archetype to the list of available ones." + (add-to-list 'pa-project-archetypes (cons name fn))) + +(defun pa-create-project () + (interactive) + (let ((name (completing-read "Archetype: " (-map 'car pa-project-archetypes) nil t))) + (call-interactively (cdr (assoc name pa-project-archetypes))))) + +(defun pa--join-patterns (patterns) + "Turn `patterns' into a string that `find' can use." + (mapconcat (lambda (pat) (format "-name \"%s\"" pat)) + patterns " -or ")) + +(defun pa--files-matching (patterns folder &optional type) + (split-string (shell-command-to-string + (format "find %s %s \\( %s \\) | head -n %s" + folder + (or type "") + (pa--join-patterns patterns) + 1000)))) + +(defun pa--instantiate-template-file (file replacements) + (with-temp-file file + (insert-file-contents-literally file) + (--each replacements + (goto-char 0) + (while (search-forward (car it) nil t) + (replace-match (cdr it)))))) + +(defun pa-sh (cmd) + (shell-command cmd pa-out)) + +(defun pa-instantiate-template-directory (template folder &rest replacements) + (let ((tmp-folder (expand-file-name (concat "__pa_tmp_" template) pa-project-folder))) + (copy-directory (expand-file-name template pa-folder) tmp-folder nil nil t) + (--each (pa--files-matching (--map (s-concat "*" (car it) "*") replacements) tmp-folder) + (rename-file it (s-replace-all replacements it))) + (--each (pa--files-matching ["*"] tmp-folder "-type f") + (pa--instantiate-template-file it replacements)) + (copy-directory tmp-folder folder) + (delete-directory tmp-folder t))) + +(put 'pa-instantiate-template-directory 'lisp-indent-function 2) + +(defmacro pa-with-new-project (project-name archetype replacements &rest body) + `(let ((folder (expand-file-name ,project-name pa-project-folder))) + (pa-instantiate-template-directory ,archetype folder ,@replacements) + (view-buffer-other-window pa-out) + (let ((default-directory (concat folder "/"))) + (pa-sh "git init") + ,@body + (pa-sh "git add -A") + (pa-sh "git ci -m \"Initial commit\"")))) + +(put 'pa-with-new-project 'lisp-indent-function 2) + +(when (file-exists-p pa-folder) + (--each (directory-files pa-folder nil "^[^#].*el$") + (load (expand-file-name it pa-folder)))) + +(provide 'project-archetypes) +;;; project-archetypes.el ends here diff --git a/site-lisp/ruby-end b/site-lisp/ruby-end deleted file mode 160000 index 5c6261a26..000000000 --- a/site-lisp/ruby-end +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5c6261a2678865bc6a80869a2015fa443c61df2b diff --git a/site-lisp/s b/site-lisp/s index 9588db702..8140902b1 160000 --- a/site-lisp/s +++ b/site-lisp/s @@ -1 +1 @@ -Subproject commit 9588db7024ff8e89820462ee2e0f24987e8c133a +Subproject commit 8140902b14f347638361927c3aade6d28d180b0b diff --git a/site-lisp/simplezen b/site-lisp/simplezen new file mode 160000 index 000000000..119fdf2c6 --- /dev/null +++ b/site-lisp/simplezen @@ -0,0 +1 @@ +Subproject commit 119fdf2c6890a0c56045ae72cf4fce0071a81481 diff --git a/site-lisp/skewer-mode/README.md b/site-lisp/skewer-mode/README.md new file mode 100644 index 000000000..d63bfc885 --- /dev/null +++ b/site-lisp/skewer-mode/README.md @@ -0,0 +1,184 @@ +# Skewer: live web development with Emacs + +Provides live interaction with JavaScript, CSS, and HTML in a web +browser. Expressions are sent on-the-fly from an editing buffer to be +evaluated in the browser, just like Emacs does with an inferior Lisp +process in Lisp modes. + +* Watch the [**demo video** on YouTube](http://youtu.be/4tyTgyzUJqM) + ([webm](http://nullprogram.s3.amazonaws.com/skewer/demo.webm)) + +**Skewer is available from [MELPA][melpa]**, which will install the +dependencies for you. This package and its dependencies are pure +Elisp, meaning setup is a breeze, the whole thing is highly portable, +and it works with many browsers. + +Dependencies: + + * [simple-httpd][simple-httpd] (available on MELPA) + * [js2-mode][js2-mode] (available on ELPA) + +## Usage + +### Quick version + +If Skewer was installed from MELPA, skip to step 3. + + 1. Place dependencies in your `load-path` or load them directly + 2. Load `skewer-mode.el` + 3. `M-x run-skewer` to attach a browser to Emacs + 4. From a `js2-mode` buffer, send forms to the browser to evaluate + +The keybindings for evaluating expressions in the browser are just +like the Lisp modes. These are provided by the minor mode +`skewer-mode`. + + * C-x C-e: Evaluate the form before the point and display + the result in the minibuffer. If given a prefix argument, insert + the result into the current buffer. + * C-M-x: Evaluate the top-level form around the point. + * C-c C-k: Load the current buffer. + * C-c C-z: Select the REPL buffer. + +The result of the expression is echoed in the minibuffer. + +Additionally, `css-mode` and `html-mode` get similar sets of bindings +for modifying the CSS rules and HTML on the current page. + +#### CSS + + * C-x C-e: Load the declaration at the point. + * C-M-x: Load the entire rule around the point. + * C-c C-k: Load the current buffer as a stylesheet. + +#### HTML + + * C-M-x: Load the HTML tag immediately around the point. + +Note: `run-skewer` uses `browse-url` to launch the browser. This may +require further setup depending on your operating system and personal +preferences. + +Multiple browsers and browser tabs can be attached to Emacs at once. +JavaScript forms are sent to all attached clients simultaneously, and +each will echo back the result individually. Use `list-skewer-clients` +to see a list of all currently attached clients. + +Sometimes Skewer's long polls from the browser will timeout after a +number of hours of inactivity. If you find the browser disconnected +from Emacs for any reason, use the browser's console to call +`skewer()` to reconnect. This avoids a page reload, which would lose +any fragile browser state you might care about. + +### Manual version + +To skewer your own document rather than the provided blank one, + + 1. Load the dependencies + 2. Load `skewer-mode.el` + 3. Start the HTTP server (`httpd-start`) + 4. Include "http://localhost:8080/skewer" as a script + (see example.html and check your `httpd-port`) + 5. Visit the document from your browser + +Skewer fully supports CORS so the document need not be hosted by Emacs +itself. A Greasemonkey userscript is provided for injecting Skewer +into any arbitrary page you're visiting without needing to modify the +page on the host. More information below. + +**Don't copy `skewer.js` anywhere or use it directly**. Emacs hosts +this script itself, manipulating it in memory before it reaches the +browser. Always access it through the servlet on the Emacs webserver +as `/skewer`. + +### Browser Support + +Skewer is known to work properly with Firefox, Chrome, Safari, Opera, +and IE8+. Except for CSS and HTML, Skewer will work in IE7 when +`document.querySelector` and `JSON` are polyfilled. If you find any +other JavaScript-supported browser that doesn't work with Skewer, +please report it. + +## REPL + +A REPL into the browser can be created with `M-x skewer-repl`, or +C-c C-z. This should work just like a console within the +browser. Messages can be logged to this REPL with `skewer.log()` (just +like `console.log()`). + +Results of expressions evaluated in the REPL are printed more +verbosely than in the minibuffer, when possible. This may help in +debugging. + +Use `M-x skewer-repl-toggle-strict-mode` to toggle strict evaluation +for expressions in the REPL. However, be aware of the +[consequences of using strict mode][strict-mode]. + +## Strict mode + +Evaluation can be done in [strict mode][strict-mode] but, +unfortunately, because strict mode `eval` is neutered the results are +completely at odds with Skewer. It's not possible to create new global +bindings in strict mode, so functions and variables defined in strict +mode evaluations can't be accessed by Skewer again later. If you want +to redefine loaded code in Skewer, make sure you disable strict mode. + +However, you *can* use strict *within* your functions since this +doesn't effect Skewer's top-level `eval`. + +## Skewering with CORS + +Skewer supports [Cross-origin Resource Sharing (CORS)][cors]. This +means you can Skewer a document hosted from any server without needing +any special changes on that server, except for including `/skewer` as +a script in that document. + +If you don't control the server from which you want to skewer pages -- +such that you can't add the Skewer's script -- the provided +Greasemonkey userscript can be used to inject it into any page you +visit. Note that this userscript will assume you're running the Skewer +server at http://localhost:8080/ (simple-httpd's default port). If +this isn't true, you need to edit the top of the userscript. + +The script isn't actually injected until you switch the toggle in the +top-right corner, the red/green triangle. + +Alternatively, the following bookmarklet will load skewer on demand: + +```js +javascript:(function(){var d=document;var s=d.createElement('script');s.src='http://localhost:8080/skewer';d.body.appendChild(s);})() +``` + +## bower + +Also provided are some functions for loading libraries from the bower +infrastructure on the fly. This is accessed with `skewer-bower-load`. +For example, I often find it useful to load jQuery when skewering a +page that doesn't have jQuery installed. + +Note: to use this **bower does *not* need to be installed**, only git. +It's just the bower infrastructure being used. Unfortunately this +infrastructure is a mess right now; many packages are in some sort of +broken state -- missing dependencies, missing metadata, broken +metadata, or an invalid repository URL. Some of this is due to +under-specification of the metadata by the bower project. + +## Motivation + +I wanted something like [swank-js][swank-js] but without all the +painful setup. Having already written an Emacs web server I was +halfway there. It took relatively little code to accomplish. + +I also didn't want to rely a browser-specific feature, like MozRepl or +WebKit's remote debugger ([kite][kite]). + +The name refers to the idea that Emacs is *skewering* the browser from +server-side. + +[simple-httpd]: https://github.com/skeeto/emacs-http-server +[js2-mode]: https://github.com/mooz/js2-mode +[melpa]: http://melpa.milkbox.net/ +[swank-js]: https://github.com/swank-js/swank-js +[strict-mode]: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode +[cors]: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing +[kite]: https://github.com/jscheid/kite diff --git a/site-lisp/skewer-mode/TODO b/site-lisp/skewer-mode/TODO new file mode 100644 index 000000000..c3b25edd0 --- /dev/null +++ b/site-lisp/skewer-mode/TODO @@ -0,0 +1,2 @@ + * eval-print-last-expression + * recover gracefully from long poll timeouts diff --git a/site-lisp/skewer-mode/UNLICENSE b/site-lisp/skewer-mode/UNLICENSE new file mode 100644 index 000000000..68a49daad --- /dev/null +++ b/site-lisp/skewer-mode/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/site-lisp/skewer-mode/cache-table.el b/site-lisp/skewer-mode/cache-table.el new file mode 100644 index 000000000..acdbc1d69 --- /dev/null +++ b/site-lisp/skewer-mode/cache-table.el @@ -0,0 +1,67 @@ +;;; cache-table.el --- a hash table with expiring entries + +;; This is free and unencumbered software released into the public domain. + +;; Author: Christopher Wellons +;; Version: 1.0 + +;;; Commentary: + +;; See the docstring of `make-cache-table'. There is no +;; `put-cache-table': use `setf' on `get-cache-table' instead. + +;;; Code: + +(eval-when-compile (require 'cl)) + +(defstruct cache-table-struct + "A cache table with expiring entries. Use `make-cache-table' to +create instances of this struct." + expire-time table) + +(defun make-cache-table (expire-time &rest keyword-args) + "Create a new cache-table with entries automatically removed +from the table after EXPIRE-TIME seconds. This function accepts +the same keyword arguments as `make-hash-table'. Entries are not +actually removed from the cache-table until an access is made to +the cache-table. + +Use `get-cache-table' to get and put (via setf) entries." + (make-cache-table-struct :expire-time expire-time + :table (apply #'make-hash-table keyword-args))) + +(defun cache-table-clear-expired (cache-table) + "Remove all expired entries from CACHE-TABLE." + (loop with expire-time = (cache-table-struct-expire-time cache-table) + with table = (cache-table-struct-table cache-table) + with dead-time = (- (float-time) expire-time) + for key being the hash-keys of table using (hash-value entry) + for (time . value) = entry + when (< time dead-time) do (remhash key table))) + +(defun get-cache-table (key cache-table &optional default) + "Access the value for KEY in CACHE-TABLE if it has not yet +expired. Behaves just like `gethash'." + (cache-table-clear-expired cache-table) + (cdr (gethash key (cache-table-struct-table cache-table) (cons 0 default)))) + +(defsetf get-cache-table (key cache-table) (value) + "Put an entry in the hash table, like (setf (gethash key table) value)." + `(progn + (cache-table-clear-expired ,cache-table) + (puthash ,key (cons (float-time) ,value) + (cache-table-struct-table ,cache-table)))) + +(defun cache-table-map (f cache-table) + "Like `maphash', call F for all non-expired entries in CACHE-TABLE." + (cache-table-clear-expired cache-table) + (maphash (lambda (k v) (funcall f k (cdr v))) + (cache-table-struct-table cache-table))) + +(defun cache-table-count (cache-table) + "Like `hash-table-count', count the number of non-expired entries." + (hash-table-count (cache-table-struct-table cache-table))) + +(provide 'cache-table) + +;;; cache-table.el ends here diff --git a/site-lisp/skewer-mode/example.html b/site-lisp/skewer-mode/example.html new file mode 100644 index 000000000..a3e301aa5 --- /dev/null +++ b/site-lisp/skewer-mode/example.html @@ -0,0 +1,9 @@ + + + + Skewer + + + + + diff --git a/site-lisp/skewer-mode/skewer-bower.el b/site-lisp/skewer-mode/skewer-bower.el new file mode 100644 index 000000000..d93fa547d --- /dev/null +++ b/site-lisp/skewer-mode/skewer-bower.el @@ -0,0 +1,204 @@ +;;; skewer-bower.el --- dynamic library loading -*- lexical-binding: t; -*- + +;; This is free and unencumbered software released into the public domain. + +;;; Commentary: + +;; This package loads libraries into the current page using the bower +;; infrastructure. Note: bower is not actually used by this package +;; and so does *not* need to be installed. Only git is required (see +;; `skewer-bower-git-executable'). It will try to learn how to run git +;; from Magit if available. + +;; The interactive command for loading libraries is +;; `skewer-bower-load'. It will prompt for a library and a version, +;; automatically fetching it from the bower infrastructure if needed. +;; For example, I often find it handy to load some version of jQuery +;; when poking around at a page that doesn't already have it loaded. + +;; Caveat: unfortunately the bower infrastructure is a mess; many +;; packages are in some sort of broken state -- missing dependencies, +;; missing metadata, broken metadata, or an invalid repository URL. +;; Some of this is due to under-specification of the metadata by the +;; bower project. Broken packages are unlikely to be loadable by +;; skewer-bower. + +;;; Code: + +(require 'cl) +(require 'skewer-mode) +(require 'simple-httpd) +(require 'magit nil t) ; optional + +(defcustom skewer-bower-cache-dir (locate-user-emacs-file "skewer-cache") + "Location of library cache (git repositories)." + :type 'string + :group 'skewer) + +(defcustom skewer-bower-endpoint "https://bower.herokuapp.com" + "Endpoint for accessing package information." + :type 'string + :group 'skewer) + +(defcustom skewer-bower-json '("bower.json" "package.json" "component.json") + "Files to search for package metadata." + :type 'list + :group 'skewer) + +; Try to match Magit's configuration if available +(if (boundp 'magit-git-executable) + (defvaralias 'skewer-bower-git-executable 'magit-git-executable) + (defcustom skewer-bower-git-executable "git" + "Name of the git executable." + :type 'string + :group 'skewer)) + +(defvar skewer-bower-packages nil + "Alist of all packages known to bower.") + +(defvar skewer-bower-refreshed nil + "List of packages that have been refreshed recently. This keeps +them from hitting the network frequently.") + +;;;###autoload +(defun skewer-bower-refresh () + "Update the package listing and packages synchronously." + (interactive) + (setf skewer-bower-refreshed nil) + (with-current-buffer + (url-retrieve-synchronously (concat skewer-bower-endpoint "/packages")) + (re-search-forward "\r?\n\r?\n") + (setf skewer-bower-packages + (sort* + (loop for package across (json-read) + collect (cons (cdr (assoc 'name package)) + (cdr (assoc 'url package)))) + #'string< :key #'car)))) + +;; Git functions + +(defun skewer-bower-cache (package) + "Return the cache repository directory for PACKAGE." + (unless (file-exists-p skewer-bower-cache-dir) + (make-directory skewer-bower-cache-dir t)) + (expand-file-name package skewer-bower-cache-dir)) + +(defun skewer-bower-git (package &rest args) + "Run git for PACKAGE's repository with ARGS." + (with-temp-buffer + (when (zerop (apply #'call-process skewer-bower-git-executable nil t nil + (format "--git-dir=%s" (skewer-bower-cache package)) + args)) + (buffer-string)))) + +(defun skewer-bower-git-clone (url package) + "Clone or fetch PACKAGE's repository from URL if needed." + (if (member package skewer-bower-refreshed) + t + (let* ((cache (skewer-bower-cache package)) + (status + (if (file-exists-p cache) + (when (skewer-bower-git package "fetch") + (push package skewer-bower-refreshed)) + (skewer-bower-git package "clone" "--bare" url cache)))) + (not (null status))))) + +(defun skewer-bower-git-show (package version file) + "Grab FILE from PACKAGE at version VERSION." + (when (string-match-p "^\\./" file) ; avoid relative paths + (setf file (substring file 2))) + (skewer-bower-git package "show" (format "%s:%s" version file))) + +(defun skewer-bower-git-tag (package) + "List all the tags in PACKAGE's repository." + (split-string (skewer-bower-git package "tag"))) + +;; Bower functions + +(defun skewer-bower-package-ensure (package) + "Ensure a package is installed in the cache and up to date. +Emit an error if the package could not be ensured." + (when (null skewer-bower-packages) (skewer-bower-refresh)) + (let ((url (cdr (assoc package skewer-bower-packages)))) + (when (null url) + (error "Unknown package: %s" package)) + (when (null (skewer-bower-git-clone url package)) + (error "Failed to fetch: %s" url)) + t)) + +(defun skewer-bower-package-versions (package) + "List the available versions for a package. Always returns at +least one version." + (skewer-bower-package-ensure package) + (or (sort (skewer-bower-git-tag package) #'string<) + (list "master"))) + +(defun skewer-bower-get-config (package &optional version) + "Get the configuration alist for PACKAGE at VERSION. Return nil +if no configuration could be found." + (skewer-bower-package-ensure package) + (unless version (setf version "master")) + (json-read-from-string + (loop for file in skewer-bower-json + for config = (skewer-bower-git-show package version file) + when config return it + finally (return "null")))) + +;; Serving the library + +(defvar skewer-bower-history () + "Library selection history for `completing-read'.") + +(defun skewer-bowser--path (package version main) + "Return the simple-httpd hosted path for PACKAGE." + (format "/skewer/bower/%s/%s/%s" package (or version "master") main)) + +(defun skewer-bower-prompt-package () + "Prompt for a package and version from the user." + (when (null skewer-bower-packages) (skewer-bower-refresh)) + (let* ((packages (mapcar #'car skewer-bower-packages)) + (selection (delete-duplicates + (append skewer-bower-history packages) :from-end t)) + (package (completing-read "Library: " selection nil t nil + 'skewer-bower-history)) + (versions (skewer-bower-package-versions package)) + (version (completing-read "Version: " (reverse versions)))) + (list package version))) + +(defun skewer-bower-guess-main (package version config) + "Attempt to determine the main entrypoint from a potentially +incomplete or incorrect bower configuration. Returns nil if +guessing failed." + (find-if (apply-partially #'skewer-bower-git-show package version) + (list (cdr (assoc 'main config)) + (concat package ".js") + package))) + +;;;###autoload +(defun skewer-bower-load (package &optional version) + "Dynamically load a library from bower into the current page." + (interactive (skewer-bower-prompt-package)) + (let* ((config (skewer-bower-get-config package)) + (deps (cdr (assoc 'dependencies config))) + (main (skewer-bower-guess-main package version config))) + (when (null main) + (error "Could not load %s (%s): no \"main\" entrypoint specified" + package version)) + (loop for (dep . version) in deps + do (skewer-bower-load (format "%s" dep) version)) + (let ((path (skewer-bowser--path package version main))) + (skewer-eval path nil :type "script")))) + +(defservlet skewer/bower application/javascript (path) + "Serve a script from the local bower repository cache." + (destructuring-bind (_ _skewer _bower package version . parts) + (split-string path "/") + (let* ((file (mapconcat #'identity parts "/")) + (contents (skewer-bower-git-show package version file))) + (if contents + (insert contents) + (httpd-error t 404))))) + +(provide 'skewer-bower) + +;;; skewer-bower.el ends here diff --git a/site-lisp/skewer-mode/skewer-css.el b/site-lisp/skewer-mode/skewer-css.el new file mode 100644 index 000000000..c17a0f31c --- /dev/null +++ b/site-lisp/skewer-mode/skewer-css.el @@ -0,0 +1,131 @@ +;;; skewer-css.el --- skewer support for live-interaction CSS + +;; This is free and unencumbered software released into the public domain. + +;;; Commentary: + +;; This minor mode provides functionality for CSS like plain Skewer +;; does for JavaScript. + +;; * C-x C-e -- `skewer-css-eval-current-declaration' +;; * C-M-x -- `skewer-css-eval-current-rule' +;; * C-c C-k -- `skewer-css-eval-buffer' + +;; These functions assume there are no comments within a CSS rule, +;; *especially* not within a declaration. In the former case, if you +;; keep the comment free of CSS syntax it should be able to manage +;; reasonably well. This may be fixed someday. + +;;; Code: + +(require 'css-mode) +(require 'skewer-mode) + +(defun skewer-css-trim (string) + "Trim and compress whitespace in the string." + (let ((cleaned (replace-regexp-in-string "[\t\n ]+" " " string))) + (replace-regexp-in-string "^[\t\n ]+\\|[\t\n ]+$" "" cleaned))) + +;; Parsing + +(defun skewer-css-beginning-of-rule () + "Move to the beginning of the current rule and return point." + (skewer-css-end-of-rule) + (let ((end (re-search-backward "{"))) + (when (re-search-backward "[}/]" nil 'start) + (forward-char)) + (re-search-forward "[^ \t\n]") + (backward-char) + (point))) + +(defun skewer-css-end-of-rule () + "Move to the end of the current rule and return point." + (if (eql (char-before) ?}) + (point) + (re-search-forward "}"))) + +(defun skewer-css-end-of-declaration () + "Move to the end of the current declaration and return point." + (if (eql (char-before) ?\;) + (point) + (re-search-forward ";"))) + +(defun skewer-css-beginning-of-declaration () + "Move to the end of the current declaration and return point." + (skewer-css-end-of-declaration) + (re-search-backward ":") + (css-backward-sexp 1) + (point)) + +(defun skewer-css-selectors () + "Return the selectors for the current rule." + (save-excursion + (let ((start (skewer-css-beginning-of-rule)) + (end (1- (re-search-forward "{")))) + (skewer-css-trim + (buffer-substring-no-properties start end))))) + +(defun skewer-css-declaration () + "Return the current declaration as a pair of strings." + (save-excursion + (let ((start (skewer-css-beginning-of-declaration)) + (end (skewer-css-end-of-declaration))) + (let* ((clip (buffer-substring-no-properties start end)) + (pair (split-string clip ":"))) + (mapcar #'skewer-css-trim pair))))) + +;; Evaluation + +(defun skewer-css (rule) + "Add RULE as a new stylesheet." + (skewer-eval rule nil :type "css")) + +(defun skewer-css-eval-current-declaration () + "Evaluate the declaration at the point." + (interactive) + (save-excursion + (let ((selectors (skewer-css-selectors)) + (rule (skewer-css-declaration)) + (start (skewer-css-beginning-of-declaration)) + (end (skewer-css-end-of-declaration))) + (skewer-flash-region start end) + (skewer-css (apply #'format "%s { %s: %s }" selectors rule))))) + +(defun skewer-css-eval-current-rule () + "Evaluate the rule at the point." + (interactive) + (save-excursion + (let* ((start (skewer-css-beginning-of-rule)) + (end (skewer-css-end-of-rule)) + (rule (buffer-substring-no-properties start end))) + (skewer-flash-region start end) + (skewer-css (skewer-css-trim rule))))) + +(defun skewer-css-eval-buffer () + "Send the entire current buffer as a new stylesheet." + (interactive) + (skewer-css (buffer-substring-no-properties (point-min) (point-max)))) + +;; Minor mode definition + +(defvar skewer-css-mode-map + (let ((map (make-sparse-keymap))) + (prog1 map + (define-key map (kbd "C-x C-e") 'skewer-css-eval-current-declaration) + (define-key map (kbd "C-M-x") 'skewer-css-eval-current-rule) + (define-key map (kbd "C-c C-k") 'skewer-css-eval-buffer))) + "Keymap for skewer-css-mode.") + +;;;###autoload +(define-minor-mode skewer-css-mode + "Minor mode for interactively loading new CSS rules." + :lighter " skewer-css" + :keymap skewer-css-mode-map + :group 'skewer) + +;;;###autoload +(add-hook 'css-mode-hook 'skewer-css-mode) + +(provide 'skewer-css) + +;;; skewer-css.el ends here diff --git a/site-lisp/skewer-mode/skewer-everything.user.js b/site-lisp/skewer-mode/skewer-everything.user.js new file mode 100644 index 000000000..ad0158d10 --- /dev/null +++ b/site-lisp/skewer-mode/skewer-everything.user.js @@ -0,0 +1,51 @@ +// ==UserScript== +// @name Skewer Everything +// @description Add a toggle button to run Skewer on the current page +// @lastupdated 2013-01-24 +// @version 1.1 +// @license Public Domain +// @include /^https?:/// +// ==/UserScript== + +var host = 'http://localhost:8080'; + +var toggle = document.createElement('div'); +toggle.onclick = inject; +toggle.style.width = '0px'; +toggle.style.height = '0px'; +toggle.style.borderStyle = 'solid'; +toggle.style.borderWidth = '0 12px 12px 0'; +toggle.style.borderColor = 'transparent #F00 transparent transparent'; +toggle.style.position = 'absolute'; +toggle.style.right = 0; +toggle.style.top = 0; +toggle.style.zIndex = 214748364; + +var injected = false; + +function inject() { + if (!injected) { + var script = document.createElement('script'); + script.src = host + '/skewer'; + document.body.appendChild(script); + toggle.style.borderRightColor = '#0F0'; + } else { + /* break skewer to disable it */ + if (unsafeWindow.skewer) { // Greasemonkey + unsafeWindow.skewer.fn = null; + } else if (unsafeWindow.window.skewer) { // Tampermonkey + unsafeWindow.window.skewer.fn = null; + } + toggle.style.borderRightColor = '#F00'; + } + injected = !injected; + GM_setValue('auto.' + location, injected); +} + +/* Don't use on iframes. */ +if (window.top === window.self) { + document.body.appendChild(toggle); + if (GM_getValue('auto.' + location)) { + inject(); + } +} diff --git a/site-lisp/skewer-mode/skewer-html.el b/site-lisp/skewer-mode/skewer-html.el new file mode 100644 index 000000000..c995fa79d --- /dev/null +++ b/site-lisp/skewer-mode/skewer-html.el @@ -0,0 +1,128 @@ +;;; skewer-html.el --- skewer support for live-interaction HTML + +;; This is free and unencumbered software released into the public domain. + +;;; Commentary: + +;; This minor mode provides functionality for HTML like plain Skewer +;; does for JavaScript. There's no clean way to replace the body and +;; head elements of a live document, so "evaluating" these elements is +;; not supported. + +;; * C-M-x -- `skewer-html-eval-tag' + +;; See also `skewer-html-fetch-selector-into-buffer' for grabbing the +;; page as it current exists. + +;;; Code: + +(require 'cl) +(require 'sgml-mode) +(require 'skewer-mode) + +;; Selector computation + +(defun skewer-html--cleanup (name) + "Cleanup tag names provided by sgml-mode." + (replace-regexp-in-string "/$" "" name)) + +(defun skewer-html--tag-after-point () + "Return the tag struct for the tag immediately following point." + (save-excursion + (forward-char 1) + (sgml-parse-tag-backward))) + +(defun skewer-html-compute-tag-nth () + "Compute the position of this tag within its parent." + (save-excursion + (let ((tag (car (last (sgml-get-context))))) + (if (null tag) + 1 + (loop with start = (sgml-tag-name tag) + with stop = (save-excursion (sgml-get-context) (point)) + with n = 1 + do (sgml-skip-tag-backward 1) + while (> (point) stop) + when (equal start (sgml-tag-name (skewer-html--tag-after-point))) + do (incf n) + finally (return n)))))) + +(defun skewer-html-compute-tag-ancestry () + "Compute the ancestry chain at point." + (save-excursion + (nreverse + (loop for nth = (skewer-html-compute-tag-nth) + for tag = (car (last (sgml-get-context))) + while tag + for name = (skewer-html--cleanup (sgml-tag-name tag)) + for type = (sgml-tag-type tag) + when (not (or (string= name "html") + (eq type 'close))) + collect (list name nth))))) + +(defun skewer-html-compute-selector () + "Compute the selector for exactly the tag around point." + (let ((ancestry (skewer-html-compute-tag-ancestry))) + (mapconcat (lambda (tag) + (format "%s:nth-of-type(%d)" (first tag) (second tag))) + ancestry " > "))) + +;; Fetching + +(defun skewer-html-fetch-selector (selector) + "Fetch the innerHTML of a selector." + (let ((result (skewer-eval-synchronously selector :type "fetchselector"))) + (if (skewer-success-p result) + (cdr (assoc 'value result)) + ""))) + +(defun skewer-html-fetch-selector-into-buffer (selector) + "Fetch the innerHTML of a selector and insert it into the active buffer." + (interactive "sSelector: ") + (insert (skewer-html-fetch-selector selector))) + +;; Evaluation + +(defun skewer-html-eval (string ancestry &optional append) + "Load HTML into a selector, optionally appending." + (let ((ancestry* (coerce ancestry 'vector))) ; for JSON + (skewer-eval string nil :type "html" :extra `((ancestry . ,ancestry*) + (append . ,append))))) + +(defun skewer-html-eval-tag () + "Load HTML from the immediately surrounding tag." + (interactive) + (let ((ancestry (skewer-html-compute-tag-ancestry))) + (save-excursion + ;; Move to beginning of opening tag + (loop for tag = (car (last (sgml-get-context))) + while (and tag (eq 'close (sgml-tag-type tag)))) + (let* ((beg (progn (point))) + (end (progn (sgml-skip-tag-forward 1) (point))) + (region (buffer-substring-no-properties beg end))) + (skewer-flash-region beg end) + (if (= (length ancestry) 1) + (error "Error: cannot eval body and head tags.") + (skewer-html-eval region ancestry nil)))))) + +;; Minor mode definition + +(defvar skewer-html-mode-map + (let ((map (make-sparse-keymap))) + (prog1 map + (define-key map (kbd "C-M-x") 'skewer-html-eval-tag))) + "Keymap for skewer-html-mode") + +;;;###autoload +(define-minor-mode skewer-html-mode + "Minor mode for interactively loading new HTML." + :lighter " skewer-html" + :keymap skewer-html-mode-map + :group 'skewer) + +;;;###autoload +(add-hook 'html-mode-hook 'skewer-html-mode) + +(provide 'skewer-html) + +;;; skewer-html.el ends here diff --git a/site-lisp/skewer-mode/skewer-mode.el b/site-lisp/skewer-mode/skewer-mode.el new file mode 100644 index 000000000..0b81c726a --- /dev/null +++ b/site-lisp/skewer-mode/skewer-mode.el @@ -0,0 +1,509 @@ +;;; skewer-mode.el --- live browser JavaScript and CSS interaction + +;; This is free and unencumbered software released into the public domain. + +;; Author: Christopher Wellons +;; URL: https://github.com/skeeto/skewer-mode +;; Version: 1.4 +;; Package-Requires: ((simple-httpd "1.4.0") (js2-mode "20090723")) + +;;; Commentary: + +;; 1. Place dependencies in your `load-path' or load them directly +;; 2. Load skewer-mode.el +;; 3. M-x `run-skewer' to attach a browser to Emacs +;; 4. From a `js2-mode' buffer, send forms to the browser to evaluate + +;; The keybindings for evaluating expressions in the browser are just +;; like the Lisp modes. These are provided by the minor mode +;; `skewer-mode'. + +;; * C-x C-e -- `skewer-eval-last-expression' +;; * C-M-x -- `skewer-eval-defun' +;; * C-c C-k -- `skewer-load-buffer' + +;; The result of the expression is echoed in the minibuffer. + +;; Additionally, `css-mode' gets a similar set of bindings for +;; modifying the CSS rules on the current page. They operate on +;; declarations and rules. + +;; Note: `run-skewer' uses `browse-url' to launch the browser. This +;; may require further setup depending on your operating system and +;; personal preferences. + +;; Multiple browsers and browser tabs can be attached to Emacs at +;; once. JavaScript forms are sent to all attached clients +;; simultaneously, and each will echo back the result +;; individually. Use `list-skewer-clients' to see a list of all +;; currently attached clients. + +;; Sometimes Skewer's long polls from the browser will timeout after a +;; number of hours of inactivity. If you find the browser disconnected +;; from Emacs for any reason, use the browser's console to call +;; skewer() to reconnect. This avoids a page reload, which would lose +;; any fragile browser state you might care about. + +;; Manual version: + +;; To skewer your own document rather than the provided blank one, + +;; 1. Load the dependencies +;; 2. Load skewer-mode.el +;; 3. Start the HTTP server (`httpd-start') +;; 4. Include "http://localhost:8080/skewer" as a script +;; (see `example.html' and check your `httpd-port') +;; 5. Visit the document from your browser + +;; Skewer fully supports CORS so the document need not be hosted by +;; Emacs itself. A Greasemonkey userscript is provided for injecting +;; Skewer into any arbitrary page you're visiting without needing to +;; modify the page on the host. + +;; With skewer-repl.el loaded, a REPL into the browser can be created +;; with M-x `skewer-repl', or C-c C-z. This should work just like a +;; console within the browser. Messages can be logged to this REPL +;; with `skewer.log()` (just like `console.log()`). + +;; Extending Skewer: + +;; Skewer is flexible and open to extension. The REPL in +;; skewer-repl.el is a partial example of this. You can extend +;; skewer.js with your own request handlers and talk to them from +;; Emacs using `skewer-eval' (or `skewer-eval-synchronously') with +;; your own custom :type. The :type string chooses the dispatch +;; function under the skewer.fn object. To inject your own JavaScript +;; into skewer.js, use `skewer-js-hook'. + +;; You can also catch messages sent from the browser not in response +;; to an explicit request. Use `skewer-response-hook' to see all +;; incoming objects. + +;;; History: + +;; Version 1.4: features +;; * Full CSS interaction +;; * Greasemonkey userscript for injection +;; * Full, working CORS support +;; * Better browser presence detection +;; Version 1.3: features and fixes +;; * Full offline support +;; * No more callback registering +;; * Fix 64-bit support +;; * Two new hooks for improved extension support +;; * More uniform keybindings with other interactive modes +;; Version 1.2: features +;; * Add a skewer-eval-print-last-expression +;; * Display evaluation time when it's long +;; * Flash the region on eval +;; * Improve JS stringification +;; Version 1.1: features and fixes +;; * Added `list-skewer-clients' +;; * Reduce the number of HTTP requests needed +;; * Fix stringification issues +;; Version 1.0: initial release + +;;; Code: + +(require 'cl) +(require 'json) +(require 'url-util) +(require 'simple-httpd) +(require 'js2-mode) +(require 'cache-table) + +(defgroup skewer nil + "Live browser JavaScript interaction." + :group 'languages) + +(defvar skewer-mode-map + (let ((map (make-sparse-keymap))) + (prog1 map + (define-key map (kbd "C-x C-e") 'skewer-eval-last-expression) + (define-key map (kbd "C-M-x") 'skewer-eval-defun) + (define-key map (kbd "C-c C-k") 'skewer-load-buffer))) + "Keymap for skewer-mode.") + +(defvar skewer-data-root (file-name-directory load-file-name) + "Location of data files needed by impatient-mode.") + +(defvar skewer-js-hook () + "Hook to run when skewer.js is being served to the browser. + +When hook functions are called, the current buffer is the buffer +to be served to the client (a defservlet), with skewer.js script +already inserted. This is the chance for other packages to insert +their own JavaScript to extend skewer in the browser, such as +adding a new type handler.") + +(defvar skewer-response-hook () + "Hook to run when a response arrives from the browser. Used for +catching messages from the browser with no associated +callback. The response object is passed to the hook function.") + +(defvar skewer-timeout 3600 + "Maximum time to wait on the browser to respond, in seconds.") + +(defvar skewer-clients () + "Browsers awaiting JavaScript snippets.") + +(defvar skewer-callbacks (make-cache-table skewer-timeout :test 'equal) + "Maps evaluation IDs to local callbacks.") + +(defvar skewer-queue () + "Queued messages for the browser.") + +(defvar skewer--last-timestamp 0 + "Timestamp of the last browser response. Use +`skewer-last-seen-seconds' to access this.") + +(defstruct skewer-client + "A client connection awaiting a response." + proc agent) + +(defun skewer-process-queue () + "Send all queued messages to clients." + (when (and skewer-queue skewer-clients) + (let ((message (pop skewer-queue)) + (sent nil)) + (while skewer-clients + (condition-case error-case + (progn + (let ((proc (skewer-client-proc (pop skewer-clients)))) + (with-temp-buffer + (insert (json-encode message)) + (httpd-send-header proc "text/plain" 200 + :Cache-Control "no-cache" + :Access-Control-Allow-Origin "*"))) + (setq skewer--last-timestamp (float-time)) + (setq sent t)) + (error nil))) + (if (not sent) (push message skewer-queue))) + (skewer-process-queue))) + +(defun skewer-clients-tabulate () + "Prepare client list for tabulated-list-mode." + (loop for client in skewer-clients collect + (let ((proc (skewer-client-proc client)) + (agent (skewer-client-agent client))) + (destructuring-bind (host port) (process-contact proc) + `(,client [,host ,(format "%d" port) ,agent]))))) + +(define-derived-mode skewer-clients-mode tabulated-list-mode "skewer-clients" + "Mode for listing browsers attached to Emacs for skewer-mode." + (setq tabulated-list-format [("Host" 12 t) + ("Port" 5 t) + ("User Agent" 0 t)]) + (setq tabulated-list-entries #'skewer-clients-tabulate) + (tabulated-list-init-header)) + +(define-key skewer-clients-mode-map (kbd "g") + (lambda () + (interactive) + (skewer-ping) + (revert-buffer))) + +(defun skewer-update-list-buffer () + "Revert the client list, due to an update." + (let ((list-buffer (get-buffer "*skewer-clients*"))) + (when list-buffer + (with-current-buffer list-buffer + (revert-buffer))))) + +;;;###autoload +(defun list-skewer-clients () + "List the attached browsers in a buffer." + (interactive) + (pop-to-buffer (get-buffer-create "*skewer-clients*")) + (skewer-clients-mode) + (tabulated-list-print)) + +(defun skewer-queue-client (proc req) + "Add a client to the queue, given the HTTP header." + (let ((agent (second (assoc "User-Agent" req)))) + (push (make-skewer-client :proc proc :agent agent) skewer-clients)) + (skewer-update-list-buffer) + (skewer-process-queue)) + +;; Servlets + +(defservlet skewer text/javascript () + (insert-file-contents (expand-file-name "skewer.js" skewer-data-root)) + (goto-char (point-max)) + (run-hooks 'skewer-js-hook)) + +(defun httpd/skewer/get (proc path query req &rest args) + (skewer-queue-client proc req)) + +(defun httpd/skewer/post (proc path query req &rest args) + (let* ((result (json-read-from-string (cadr (assoc "Content" req)))) + (id (cdr (assoc 'id result))) + (type (cdr (assoc 'type result))) + (callback (get-cache-table id skewer-callbacks))) + (setq skewer--last-timestamp (float-time)) + (when callback + (funcall callback result)) + (if id + (skewer-queue-client proc req) + (with-temp-buffer + (httpd-send-header proc "text/plain" 200 + :Access-Control-Allow-Origin "*"))) + (dolist (hook skewer-response-hook) + (funcall hook result)))) + +(defservlet skewer/demo text/html () + (insert-file-contents (expand-file-name "example.html" skewer-data-root))) + +;; Minibuffer display + +(defun skewer-success-p (result) + "Return T if result was a success." + (equal "success" (cdr (assoc 'status result)))) + +(define-derived-mode skewer-error-mode special-mode "skewer-error" + :group 'skewer + "Mode for displaying JavaScript errors returned by skewer-mode." + (setq truncate-lines t)) + +(defface skewer-error-face + '((((class color) (background light)) + :foreground "red" :underline t) + (((class color) (background dark)) + :foreground "red" :underline t)) + "Face for JavaScript errors." + :group 'skewer) + +(defun skewer--error (string) + "Return STRING propertized as an error message." + (propertize (or string "") 'font-lock-face 'skewer-error-face)) + +(defun skewer-post-minibuffer (result) + "Report results in the minibuffer or the error buffer." + (if (skewer-success-p result) + (let ((value (cdr (assoc 'value result))) + (time (cdr (assoc 'time result)))) + (if (and time (> time 1.0)) + (message "%s (%.3f seconds)" value time) + (message "%s" value))) + (with-current-buffer (pop-to-buffer (get-buffer-create "*skewer-error*")) + (let ((inhibit-read-only t) + (error (cdr (assoc 'error result)))) + (erase-buffer) + (skewer-error-mode) + (insert (skewer--error (cdr (assoc 'name error))) ": ") + (insert (or (cdr (assoc 'message error)) "") "\n\n") + (insert (or (cdr (assoc 'stack error)) "") "\n\n") + (insert (format "Expression: %s\n\n" + (if (cdr (assoc 'strict result)) "(strict)" "")) + (cdr (assoc 'eval error))) + (goto-char (point-min)))))) + +;; Evaluation functions + +(defun* skewer-eval (string &optional callback + &key verbose strict (type "eval") extra) + "Evaluate STRING in the waiting browsers, giving the result to CALLBACK. + +:VERBOSE -- if T, the return will try to be JSON encoded +:STRICT -- if T, expression is evaluated with 'use strict' +:TYPE -- chooses the JavaScript handler (default: eval) +:EXTRA -- additional alist keys to append to the request object" + (let* ((id (format "%x" (random most-positive-fixnum))) + (request `((type . ,type) + (eval . ,string) + (id . ,id) + (verbose . ,verbose) + (strict . ,strict) + ,@extra))) + (prog1 request + (setf (get-cache-table id skewer-callbacks) callback) + (setq skewer-queue (append skewer-queue (list request))) + (skewer-process-queue)))) + +(defun skewer-eval-synchronously (string &rest args) + "Just like `skewer-eval' but synchronously, so don't provide a +callback. Use with caution." + (lexical-let ((result nil)) + (apply #'skewer-eval string (lambda (v) (setq result v)) args) + (loop until result + do (accept-process-output nil 0.01) + finally (return result)))) + +(defun skewer--save-point (f &rest args) + "Return a function that calls F with point at the current point." + (let ((saved-point (point))) + (lambda (&rest more) + (save-excursion + (goto-char saved-point) + (apply f (append args more)))))) + +(defun* skewer-ping () + "Ping the browser to test that it's still alive." + (unless (null skewer-clients) ; don't queue pings + (skewer-eval (prin1-to-string (float-time)) nil :type "ping"))) + +(defun skewer-last-seen-seconds () + "Return the number of seconds since the browser was last seen." + (skewer-ping) ; make sure it's still alive next request + (- (float-time) skewer--last-timestamp)) + +(defun skewer-mode-strict-p () + "Return T if buffer contents indicates strict mode." + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (js2-forward-sws) + (forward-char 1) + (let* ((stricts '("\"use strict\"" "'use strict'")) + (node (js2-node-at-point)) + (code (buffer-substring-no-properties (js2-node-abs-pos node) + (js2-node-abs-end node)))) + (and (member code stricts) t))))) + +(defun skewer-flash-region (start end &optional timeout) + "Temporarily highlight region from START to END." + (let ((overlay (make-overlay start end))) + (overlay-put overlay 'face 'secondary-selection) + (run-with-timer (or timeout 0.2) nil 'delete-overlay overlay))) + +(defun skewer-get-last-expression () + "Return the JavaScript expression before the point as a +list: (string start end)." + (save-excursion + (js2-backward-sws) + (backward-char) + (let ((node (js2-node-at-point nil t))) + (when (eq js2-FUNCTION (js2-node-type (js2-node-parent node))) + (setq node (js2-node-parent node))) + (when (js2-ast-root-p node) + (error "no expression found")) + (let ((start (js2-node-abs-pos node)) + (end (js2-node-abs-end node))) + (list (buffer-substring-no-properties start end) start end))))) + +(defun skewer-eval-last-expression (&optional prefix) + "Evaluate the JavaScript expression before the point in the +waiting browser. If invoked with a prefix argument, insert the +result into the current buffer." + (interactive "P") + (if prefix + (skewer-eval-print-last-expression) + (if js2-mode-buffer-dirty-p + (js2-mode-wait-for-parse + (skewer--save-point #'skewer-eval-last-expression)) + (destructuring-bind (string start end) (skewer-get-last-expression) + (skewer-flash-region start end) + (skewer-eval string #'skewer-post-minibuffer))))) + +(defun skewer-get-defun () + "Return the toplevel JavaScript expression around the point as +a list: (string start end)." + (save-excursion + (js2-backward-sws) + (backward-char) + (let ((node (js2-node-at-point nil t))) + (when (js2-ast-root-p node) + (error "no expression found")) + (while (and (js2-node-parent node) + (not (js2-ast-root-p (js2-node-parent node)))) + (setf node (js2-node-parent node))) + (let ((start (js2-node-abs-pos node)) + (end (js2-node-abs-end node))) + (list (buffer-substring-no-properties start end) start end))))) + +(defun skewer-eval-defun () + "Evaluate the JavaScript expression before the point in the +waiting browser." + (interactive) + (if js2-mode-buffer-dirty-p + (js2-mode-wait-for-parse (skewer--save-point #'skewer-eval-defun)) + (destructuring-bind (string start end) (skewer-get-defun) + (skewer-flash-region start end) + (skewer-eval string #'skewer-post-minibuffer)))) + +;; Print last expression + +(defvar skewer-eval-print-map (make-cache-table skewer-timeout :test 'equal) + "A mapping of evaluation IDs to insertion points.") + +(defun skewer-post-print (result) + "Insert the result after its source expression." + (if (not (skewer-success-p result)) + (skewer-post-minibuffer result) + (let* ((id (cdr (assoc 'id result))) + (pos (get-cache-table id skewer-eval-print-map))) + (when pos + (with-current-buffer (car pos) + (goto-char (cdr pos)) + (insert (cdr (assoc 'value result)) "\n")))))) + +(defun skewer-eval-print-last-expression () + "Evaluate the JavaScript expression before the point in the +waiting browser and insert the result in the buffer at point." + (interactive) + (if js2-mode-buffer-dirty-p + (js2-mode-wait-for-parse + (skewer--save-point #'skewer-eval-print-last-expression)) + (destructuring-bind (string start end) (skewer-get-defun) + (skewer-flash-region start end) + (insert "\n") + (let* ((request (skewer-eval string #'skewer-post-print :verbose t)) + (id (cdr (assoc 'id request))) + (pos (cons (current-buffer) (point)))) + (setf (get-cache-table id skewer-eval-print-map) pos))))) + +;; Script loading + +(defvar skewer-hosted-scripts (make-cache-table skewer-timeout) + "Map of hosted scripts to IDs.") + +(defun skewer-host-script (string) + "Host script STRING from the script servlet, returning the script ID." + (let ((id (random most-positive-fixnum))) + (prog1 id + (setf (get-cache-table id skewer-hosted-scripts) string)))) + +(defun skewer-load-buffer () + "Load the entire current buffer into the browser. A snapshot of +the buffer is hosted so that browsers visiting late won't see an +inconsistent buffer." + (interactive) + (lexical-let ((id (skewer-host-script (buffer-string))) + (buffer-name (buffer-name))) + (skewer-eval (format "/skewer/script/%d/%s" + id (url-hexify-string buffer-name)) + (lambda (_) (message "%s loaded" buffer-name)) + :type "script"))) + +(defservlet skewer/script text/javascript (path) + (let ((id (string-to-number (nth 3 (split-string path "/"))))) + (insert (get-cache-table id skewer-hosted-scripts "")))) + +;; Define the minor mode + +;;;###autoload +(define-minor-mode skewer-mode + "Minor mode for interacting with a browser." + :lighter " skewer" + :keymap skewer-mode-map + :group 'skewer) + +;;;###autoload +(add-hook 'js2-mode-hook 'skewer-mode) + +;;;###autoload +(defun run-skewer () + "Attach a browser to Emacs for a skewer JavaScript REPL. Uses +`browse-url' to launch a browser." + (interactive) + (httpd-start) + (browse-url (format "http://127.0.0.1:%d/skewer/demo" httpd-port))) + +;; Local Variables: +;; lexical-binding: t +;; End: + +(provide 'skewer-mode) + +;;; skewer-mode.el ends here diff --git a/site-lisp/skewer-mode/skewer-repl.el b/site-lisp/skewer-mode/skewer-repl.el new file mode 100644 index 000000000..6d769f0d9 --- /dev/null +++ b/site-lisp/skewer-mode/skewer-repl.el @@ -0,0 +1,124 @@ +;;; skewer-repl.el --- create a REPL in a visiting browser + +;; This is free and unencumbered software released into the public domain. + +;;; Commentary: + +;; This is largely based on of IELM's code. Run `skewer-repl' to +;; switch to the REPL buffer and evaluate code. Use +;; `skewer-repl-toggle-strict-mode' to turn strict mode on and off. + +;;; Code: + +(require 'comint) +(require 'skewer-mode) + +(defcustom skewer-repl-strict-p nil + "When non-NIL, all REPL evaluations are done in strict mode." + :type 'boolean + :group 'skewer) + +(defcustom skewer-repl-prompt "js> " + "Prompt string for JavaScript REPL." + :type 'string + :group 'skewer) + +(defvar skewer-repl-welcome + (propertize "*** Welcome to Skewer ***\n" + 'font-lock-face 'font-lock-comment-face) + "Header line to show at the top of the REPL buffer. Hack +notice: this allows log messages to appear before anything is +evaluated because it provides insertable space at the top of the +buffer.") + +(defun skewer-repl-process () + "Return the process for the skewer REPL." + (get-buffer-process (current-buffer))) + +(defface skewer-repl-log-face + '((((class color) (background light)) + :foreground "#77F") + (((class color) (background dark)) + :foreground "#77F")) + "Face for skewer.log() messages." + :group 'skewer) + +(define-derived-mode skewer-repl-mode comint-mode "js-REPL" + "Provide a REPL into the visiting browser." + :group 'skewer + :syntax-table emacs-lisp-mode-syntax-table + (setq comint-prompt-regexp (concat "^" (regexp-quote skewer-repl-prompt))) + (setq comint-input-sender 'skewer-input-sender) + (unless (comint-check-proc (current-buffer)) + (insert skewer-repl-welcome) + (start-process "skewer-repl" (current-buffer) nil) + (set-process-query-on-exit-flag (skewer-repl-process) nil) + (goto-char (point-max)) + (set (make-local-variable 'comint-inhibit-carriage-motion) t) + (comint-output-filter (skewer-repl-process) skewer-repl-prompt) + (set-process-filter (skewer-repl-process) 'comint-output-filter))) + +(defun skewer-repl-toggle-strict-mode () + "Toggle strict mode for expressions evaluated by the REPL." + (interactive) + (setq skewer-repl-strict-p (not skewer-repl-strict-p)) + (message "REPL strict mode %s" + (if skewer-repl-strict-p "enabled" "disabled"))) + +(defun skewer-input-sender (proc input) + "REPL comint handler." + (skewer-eval input 'skewer-post-repl + :verbose t :strict skewer-repl-strict-p)) + +(defun skewer-post-repl (result) + "Callback for reporting results in the REPL." + (let ((buffer (get-buffer "*skewer-repl*")) + (output (cdr (assoc 'value result)))) + (when buffer + (with-current-buffer buffer + (comint-output-filter (skewer-repl-process) + (concat output "\n" skewer-repl-prompt)))))) + +(defvar skewer-repl-types + '(("log" . skewer-repl-log-face) + ("error" . skewer-error-face)) + "Faces to use for different types of log messages.") + +(defun skewer-post-log (log) + "Callback for logging messages to the REPL." + (let* ((buffer (get-buffer "*skewer-repl*")) + (face (cdr (assoc (cdr (assoc 'type log)) skewer-repl-types))) + (output (propertize (cdr (assoc 'value log)) 'font-lock-face face))) + (when buffer + (with-current-buffer buffer + (save-excursion + (goto-char (point-max)) + (forward-line 0) + (backward-char) + (insert (concat "\n" output ""))))))) + +;;;###autoload +(defun skewer-repl--response-hook (response) + "Catches all browser messages logging some to the REPL." + (let ((type (cdr (assoc 'type response)))) + (when (member type '("log" "error")) + (skewer-post-log response)))) + +;;;###autoload +(defun skewer-repl () + "Start a JavaScript REPL to be evaluated in the visiting browser." + (interactive) + (when (not (get-buffer "*skewer-repl*")) + (with-current-buffer (get-buffer-create "*skewer-repl*") + (skewer-repl-mode))) + (pop-to-buffer (get-buffer "*skewer-repl*"))) + +;;;###autoload +(eval-after-load 'skewer-mode + '(progn + (add-hook 'skewer-response-hook #'skewer-repl--response-hook) + (define-key skewer-mode-map (kbd "C-c C-z") #'skewer-repl))) + +(provide 'skewer-repl) + +;;; skewer-repl.el ends here diff --git a/site-lisp/skewer-mode/skewer.js b/site-lisp/skewer-mode/skewer.js new file mode 100644 index 000000000..0cdf3bb6b --- /dev/null +++ b/site-lisp/skewer-mode/skewer.js @@ -0,0 +1,386 @@ +/** + * @fileOverview Live browser interaction with Emacs + * @version 1.4 + */ + +/** + * Connects to Emacs and waits for a request. After handling the + * request it sends back the results and queues itself for another + * request. + * @namespace Holds all of Skewer's functionality. + */ +function skewer() { + function callback(request) { + var result = skewer.fn[request.type](request); + if (result) { + result = skewer.extend({ + id: request.id, + type: request.type, + status: 'success', + value: '' + }, result); + skewer.postJSON(skewer.host + "/skewer/post", result, callback); + } else { + skewer.getJSON(skewer.host + "/skewer/get", callback); + } + }; + skewer.getJSON(skewer.host + "/skewer/get", callback); +} + +/** + * Get a JSON-encoded object from a server. + * @param {String} url The location of the remote server + * @param {Function} [callback] The callback to receive a response object + */ +skewer.getJSON = function(url, callback) { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState === 4 && xhr.status === 200) { + callback(JSON.parse(xhr.responseText)); + } + }; + xhr.open('GET', url, true); + xhr.send(); +}; + +/** + * Send a JSON-encoded object to a server. + * @param {String} url The location of the remote server + * @param {Object} object The object to transmit to the server + * @param {Function} [callback] The callback to receive a response object + */ +skewer.postJSON = function(url, object, callback) { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + if (callback && xhr.readyState === 4 && xhr.status === 200) { + callback(JSON.parse(xhr.responseText)); + } + }; + xhr.open('POST', url, true); + xhr.setRequestHeader("Content-Type", "text/plain"); // CORS + xhr.send(JSON.stringify(object)); +}; + +/** + * Add the properties other objects to a target object (jQuery.extend). + * @param {Object} target The object to receive new properties + * @param {...Object} objects Source objects for properties + * @returns The target object + */ +skewer.extend = function(target) { + for (var i = 1; i < arguments.length; i++) { + var object = arguments[i]; + for (var key in object) { + if (object.hasOwnProperty(key)) { + target[key] = object[key]; + } + } + } + return target; +}; + +/** + * Globally evaluate an expression and return the result. This + * only works when the implementation's indirect eval performs + * a global eval. If not, there's no alternative, since a return value + * is essential. + * + * @see http://perfectionkills.com/global-eval-what-are-the-options/ + * + * @param expression A string containing an expression to evaluate + * @returns The result of the evaluation + */ +skewer.globalEval = (function() { + var eval0 = (function(original, Object) { + try { + return [eval][0]('Object') === original; + } catch (e) { + return false; + } + }(Object, false)); + if (eval0) { + return function(expression) { + return [eval][0](expression); + }; + } else { + return function(expression) { // Safari + return eval.call(window, expression); + }; + } +}()); + +/** + * Handlers accept a request object from Emacs and return either a + * logical false (no response) or an object to return to Emacs. + * @namespace Request handlers. + */ +skewer.fn = {}; + +/** + * Handles an code evaluation request from Emacs. + * @param request The request object sent by Emacs + * @returns The result object to be returned to Emacs + */ +skewer.fn.eval = function(request) { + var result = { + strict: request.strict + }; + var start = Date.now(); + try { + var prefix = request.strict ? '"use strict";\n' : ""; + var value = skewer.globalEval(prefix + request.eval); + result.value = skewer.safeStringify(value, request.verbose); + } catch (error) { + result = skewer.errorResult(error, result, request); + } + result.time = (Date.now() - start) / 1000; + return result; +}; + +/** + * Load a hosted script named by the request. + * @param request The request object sent by Emacs + * @returns The result object to be returned to Emacs + */ +skewer.fn.script = function(request) { + var script = document.createElement('script'); + script.src = skewer.host + request.eval; + document.body.appendChild(script); + return {value: JSON.stringify(request.eval)}; +}; + +/** + * A keep-alive and connecton testing handler. + * @param request The request object sent by Emacs + * @returns The result object to be returned to Emacs + */ +skewer.fn.ping = function(request) { + return { + type: 'pong', + date: Date.now() / 1000, + value: request.eval + }; +}; + +/** + * Establish a new stylesheet with the provided value. + */ +skewer.fn.css = function(request) { + var style = document.createElement('style'); + style.type = 'text/css'; + if (style.styleSheet) { // < IE9 + style.styleSheet.cssText = request.eval; + } else { + style.appendChild(document.createTextNode(request.eval)); + } + document.body.appendChild(style); + return {}; +}; + +/** + * HTML evaluator, appends or replaces a selection with given HTML. + */ +skewer.fn.html = function(request) { + function buildSelector(ancestry) { + return ancestry.map(function(tag) { + return tag[0] + ':nth-of-type(' + tag[1] + ')'; + }).join(' > '); + } + function query(ancestry) { + return document.querySelector(buildSelector(ancestry)); + } + function htmlToNode(html) { + var wrapper = document.createElement('div'); + wrapper.innerHTML = html; + return wrapper.firstChild; + } + + var target = query(request.ancestry); + + if (target == null) { + /* Determine missing part of the ancestry. */ + var path = request.ancestry.slice(0); // copy + var missing = []; + while (query(path) == null) { + missing.push(path.pop()); + } + + /* Build up the missing elements. */ + target = query(path); + while (missing.length > 0) { + var tag = missing.pop(), + name = tag[0], + nth = tag[1]; + var empty = null; + var count = target.querySelectorAll(name).length; + for (; count < nth; count++) { + empty = document.createElement(tag[0]); + target.appendChild(empty); + } + target = empty; + } + } + + target.parentNode.replaceChild(htmlToNode(request.eval), target); + return {}; +}; + +/** + * Fetch the HTML contents of selector. + */ +skewer.fn.fetchselector = function(request) { + var element = document.querySelector(request.eval); + return { value: element.innerHTML }; +}; + +/** + * Host of the skewer script (CORS support). + * @type string + */ +(function() { + var script = document.querySelector('script[src$="/skewer"]'); + if (script) { + skewer.host = script.src.match(/\w+:\/\/[^/]+/)[0]; + } else { + skewer.host = ''; // default to the current host + } +}()); + +/** + * Stringify a potentially circular object without throwing an exception. + * @param object The object to be printed. + * @param {boolean} verbose Enable more verbose output. + * @returns {string} The printed object. + */ +skewer.safeStringify = function (object, verbose) { + "use strict"; + var circular = "#"; + var seen = []; + + var stringify = function(obj) { + if (obj === true) { + return "true"; + } else if (obj === false) { + return "false"; + } else if (obj === undefined) { + return "undefined"; + } else if (obj === null) { + return "null"; + } else if (typeof obj === "number") { + return obj.toString(); + } else if (obj instanceof Array) { + if (seen.indexOf(obj) >= 0) { + return circular; + } else { + seen.push(obj); + return "[" + obj.map(function(e) { + return stringify(e); + }).join(", ") + "]"; + } + } else if (typeof obj === "string") { + return JSON.stringify(obj); + } else if (typeof obj === "function") { + if (verbose) + return obj.toString(); + else + return "Function"; + } else if (Object.prototype.toString.call(obj) === '[object Date]') { + if (verbose) + return JSON.stringify(obj); + else + return obj.toString(); + } else { + if (verbose) { + if (seen.indexOf(obj) >= 0) + return circular; + else + seen.push(obj); + var pairs = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var pair = JSON.stringify(key) + ":"; + pair += stringify(obj[key]); + pairs.push(pair); + } + } + return "{" + pairs.join(',') + "}"; + } else { + try { + return obj.toString(); + } catch (error) { + return ({}).toString(); + } + } + } + }; + + try { + return stringify(object); + } catch (error) { + return skewer.safeStringify(object, false); + } +}; + +/** + * Log an object to the Skewer REPL in Emacs (console.log). + * @param message The object to be logged. + */ +skewer.log = function(message) { + "use strict"; + var log = { + type: "log", + value: skewer.safeStringify(message, true) + }; + skewer.postJSON(skewer.host + "/skewer/post", log); +}; + +/** + * Report an error event to the REPL. + * @param event An error event object. + */ +skewer.error = function(event) { + "use strict"; + var log = { + type: "error", + value: event.message + }; + skewer.postJSON(skewer.host + "/skewer/post", log); +}; + +/** + * Prepare a result when an error occurs evaluating Javascript code. + * @param error The error object given by catch. + * @param result The resutl object to return to Emacs. + * @param request The request object from Emacs. + * @return The result object to send back to Emacs. + */ +skewer.errorResult = function(error, result, request) { + "use strict"; + return skewer.extend({}, result, { + value: error.toString(), + status: 'error', + error: { + name: error.name, + stack: error.stack, + type: error.type, + message: error.message, + eval: request.eval + } + }); +}; + +if (window.addEventListener) { + window.addEventListener('error', skewer.error); + if (document.readyState === 'complete') { + skewer(); + } else { + window.addEventListener('load', skewer); + } +} else { // < IE9 + window.attachEvent('onerror', skewer.error); + if (document.readyState === 'complete') { + skewer(); + } else { + window.attachEvent('onload', skewer); + } +} diff --git a/site-lisp/smart-forward b/site-lisp/smart-forward index 445b99d5a..ccc7d819a 160000 --- a/site-lisp/smart-forward +++ b/site-lisp/smart-forward @@ -1 +1 @@ -Subproject commit 445b99d5ac5aa845962382d6954b5e1f816578b7 +Subproject commit ccc7d819abd515a28e8184ae4ac5bc706ceaf284 diff --git a/site-lisp/tagedit b/site-lisp/tagedit index f430f4a07..13f478a6a 160000 --- a/site-lisp/tagedit +++ b/site-lisp/tagedit @@ -1 +1 @@ -Subproject commit f430f4a077fe5258631ce1728c722992dd22f253 +Subproject commit 13f478a6a562a1d330b5b2b363c38a68294ed44b diff --git a/site-lisp/tern b/site-lisp/tern new file mode 160000 index 000000000..bcb3722c4 --- /dev/null +++ b/site-lisp/tern @@ -0,0 +1 @@ +Subproject commit bcb3722c489144a072b230439022aaafe54849c2 diff --git a/site-lisp/zencoding b/site-lisp/zencoding deleted file mode 160000 index fc15836a9..000000000 --- a/site-lisp/zencoding +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc15836a9da44ad5bd7954de28c5549b4feedbaf diff --git a/snippets/crappy-jsp-mode/elvariable b/snippets/crappy-jsp-mode/elvariable new file mode 100644 index 000000000..d1c681511 --- /dev/null +++ b/snippets/crappy-jsp-mode/elvariable @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: elvariable +# key: el +# -- +<%--@elvariable id="$1" type="$2"--%> \ No newline at end of file diff --git a/snippets/html-mode/link b/snippets/html-mode/link new file mode 100644 index 000000000..963950d71 --- /dev/null +++ b/snippets/html-mode/link @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: link +# key: link +# -- + \ No newline at end of file diff --git a/snippets/html-mode/oocss-module b/snippets/html-mode/oocss-module index 4c7dbce0f..e805e2455 100644 --- a/snippets/html-mode/oocss-module +++ b/snippets/html-mode/oocss-module @@ -1,8 +1,7 @@ -# -*- mode: snippet -*- -# name: oocss-module # key: mod +# name: oocss-module # -- -
+
$0 diff --git a/snippets/html-mode/strong b/snippets/html-mode/strong new file mode 100644 index 000000000..c896929a2 --- /dev/null +++ b/snippets/html-mode/strong @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: strong +# key: strong +# -- +$0 \ No newline at end of file diff --git a/snippets/js-mode/directive-oiiku-shared b/snippets/js-mode/directive-oiiku-shared new file mode 100644 index 000000000..e50b3630a --- /dev/null +++ b/snippets/js-mode/directive-oiiku-shared @@ -0,0 +1,13 @@ +# key: ng +# name: directive-oiiku-shared +# -- +angular.module("OIIKU_SHARED") + .directive("`(s-lower-camel-case (buffer-file-name-body))`", function (getContextPath) { + return { + restrict: "E", + templateUrl: getContextPath("angular-shared") + "/`(buffer-file-name-body)`.html", + link: function () { + + } + }; + }); \ No newline at end of file diff --git a/snippets/js-mode/for b/snippets/js-mode/for new file mode 100644 index 000000000..3fc8bfbc2 --- /dev/null +++ b/snippets/js-mode/for @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: for +# key: for +# -- +for (var i = 0, l = ${num}; i < l; i++) {$0} \ No newline at end of file diff --git a/snippets/js-mode/immediately-invoked-function-expression.yasnippet b/snippets/js-mode/immediately-invoked-function-expression.yasnippet index f9ef20e62..770a92767 100644 --- a/snippets/js-mode/immediately-invoked-function-expression.yasnippet +++ b/snippets/js-mode/immediately-invoked-function-expression.yasnippet @@ -1,7 +1,8 @@ # -*- mode: snippet -*- # name: immediately-invoked-function-expression -# key: f( +# key: ff # -- (function (${2:${1:$(buster--shortcuts-for-globals yas/text)}}) { - $0 + `(buster--maybe-use-strict) + `$0 }(${1:`(if buster-add-default-global-to-iife buster-default-global)`})); diff --git a/snippets/js-mode/node.require.yasnippet b/snippets/js-mode/node.require.yasnippet index 4af7fedc4..670186ddd 100644 --- a/snippets/js-mode/node.require.yasnippet +++ b/snippets/js-mode/node.require.yasnippet @@ -2,4 +2,4 @@ # name: node.require # key: req # -- -var ${3:${1:$(lower-camel-case (file-name-nondirectory yas/text))}} = require("${1:sys}")$2;$0 \ No newline at end of file +var ${3:${1:$(lower-camel-case (file-name-nondirectory yas/text))}} = require("${1:fs}")$2;$0 \ No newline at end of file diff --git a/snippets/js-mode/try b/snippets/js-mode/try new file mode 100644 index 000000000..52720b9c3 --- /dev/null +++ b/snippets/js-mode/try @@ -0,0 +1,8 @@ +# -*- mode: snippet -*- +# name: try +# key: try +# -- +try { + $0 +} catch (e) { +} \ No newline at end of file diff --git a/themes/default-black-theme.el b/themes/default-black-theme.el new file mode 100644 index 000000000..1dbb75507 --- /dev/null +++ b/themes/default-black-theme.el @@ -0,0 +1,16 @@ +(deftheme default-black + "Automatically created 2013-05-20.") + +(custom-theme-set-faces + 'default-black + '(default ((t (:inherit nil :stipple nil :background "Black" :foreground "White" :inverse-video nil :box nil :strike-t*hrough nil :overline nil :underline nil :slant normal :weight normal :width normal :height 105)))) + '(highlight ((((class color) (min-colors 88) (background dark)) (:background "#111111")))) + '(region ((nil (:background "#464740")))) + '(hl-line ((nil (:background "#222222")))) + '(yas/field-highlight-face ((nil (:background "#333399")))) + '(js2-function-param-face ((t (:foreground "LightGoldenrod")))) + '(font-lock-warning-face ((nil (:foreground "#ff6666")))) + '(show-paren-match ((nil (:background "#333399")))) + '(show-paren-mismatch ((((class color)) (:background "red"))))) + +(provide-theme 'default-black) diff --git a/themes/prez-theme.el b/themes/prez-theme.el new file mode 100644 index 000000000..a33b01da5 --- /dev/null +++ b/themes/prez-theme.el @@ -0,0 +1,803 @@ +;;; prez-theme.el --- Modified low-contrast Zenburn-inverted theme for presentations + +;; Author: Andrey Kotlarski +;; Modified by: Magnar Sveen (based on Bodil Stokke's presentation colors) +;; URL: https://github.com/m00natic/prez-theme +;; Version: 20130417.2351 +;; X-Original-Version: 2.0 + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Derived from Bozhidar Batsov's port of the Zenburn theme +;; located here https://github.com/bbatsov/zenburn-emacs + +;;; Code: + +(deftheme prez "Presentation theme.") + +(let ((class '((class color) (min-colors 89))) + ;; Zenburn palette reversed + ;; colors with -x are lighter, colors with +x are darker + (azenburn-fg "#232333") + (azenburn-fg-1 "#9a9aaa") + (azenburn-bg-1 "#d4d4d4") + (azenburn-bg-05 "#c7c7c7") + (azenburn-bg "#c0c0c0") + (azenburn-bg+1 "#b0b0b0") + (azenburn-bg+2 "#a0a0a0") + (azenburn-bg+3 "#909090") + (azenburn-blue+1 "#235c5c") + (azenburn-blue "#336c6c") + (azenburn-blue-1 "#437c7c") + (azenburn-blue-2 "#538c8c") + (azenburn-blue-3 "#639c9c") + (azenburn-blue-4 "#73acac") + (azenburn-light-blue "#205070") + (azenburn-dark-blue "#0f2050") + (azenburn-dark-blue-1 "#1f3060") + (azenburn-dark-blue-2 "#2f4070") + (azenburn-violet-1 "#a080a0") + (azenburn-violet "#806080") + (azenburn-violet+1 "#704d70") + (azenburn-violet+2 "#603a60") + (azenburn-violet+3 "#502750") + (azenburn-violet+4 "#401440") + (azenburn-bordeaux "#6c1f1c") + (azenburn-beige+1 "#6b400c") + (azenburn-beige "#732f2c") + (azenburn-beige-1 "#834744") + (azenburn-beige-2 "#935f5c") + (azenburn-beige-3 "#a37774") + (azenburn-beige-4 "#b38f8c") + (azenburn-beige-5 "#c99f9f") + (azenburn-green "#23733c")) + (custom-theme-set-faces + 'prez + '(button ((t (:underline t)))) + `(link ((t (:foreground ,azenburn-dark-blue :underline t :weight bold)))) + `(link-visited ((t (:foreground ,azenburn-dark-blue-2 :underline t :weight normal)))) + + ;;; basic coloring + `(default ((t (:foreground "#000000" :background "#ffffff")))) + `(cursor ((t (:foreground ,azenburn-fg :background "black")))) + `(escape-glyph ((t (:foreground ,azenburn-dark-blue :bold t)))) + `(fringe ((t (:foreground ,azenburn-fg :background "#f0f0f0")))) + `(header-line ((t (:foreground ,azenburn-dark-blue + :background ,azenburn-bg-1 + :box (:line-width -1 :style released-button))))) + `(highlight ((t (:background ,azenburn-bg-05)))) + `(success ((t (:foreground ,azenburn-violet :weight bold)))) + `(warning ((t (:foreground ,azenburn-light-blue :weight bold)))) + + ;;; compilation + `(compilation-column-face ((t (:foreground ,azenburn-dark-blue)))) + `(compilation-enter-directory-face ((t (:foreground ,azenburn-violet)))) + `(compilation-error-face ((t (:foreground ,azenburn-blue-1 :weight bold :underline t)))) + `(compilation-face ((t (:foreground ,azenburn-fg)))) + `(compilation-info-face ((t (:foreground ,azenburn-beige)))) + `(compilation-info ((t (:foreground ,azenburn-violet+4 :underline t)))) + `(compilation-leave-directory-face ((t (:foreground ,azenburn-violet)))) + `(compilation-line-face ((t (:foreground ,azenburn-dark-blue)))) + `(compilation-line-number ((t (:foreground ,azenburn-dark-blue)))) + `(compilation-message-face ((t (:foreground ,azenburn-beige)))) + `(compilation-warning-face ((t (:foreground ,azenburn-light-blue :weight bold :underline t)))) + `(compilation-mode-line-exit ((t (:foreground ,azenburn-violet+2 :weight bold)))) + `(compilation-mode-line-fail ((t (:foreground ,azenburn-blue :weight bold)))) + `(compilation-mode-line-run ((t (:foreground ,azenburn-dark-blue :weight bold)))) + + ;;; grep + `(grep-context-face ((t (:foreground ,azenburn-fg)))) + `(grep-error-face ((t (:foreground ,azenburn-blue-1 :weight bold :underline t)))) + `(grep-hit-face ((t (:foreground ,azenburn-beige)))) + `(grep-match-face ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(match ((t (:background ,azenburn-bg-1 :foreground ,azenburn-light-blue :weight bold)))) + + ;; faces used by isearch + `(isearch ((t (:foreground ,azenburn-dark-blue-2 :weight bold :background ,azenburn-bg-1)))) + `(isearch-fail ((t (:foreground ,azenburn-fg :background ,azenburn-blue-4)))) + `(lazy-highlight ((t (:foreground ,azenburn-dark-blue-2 :weight bold :background ,azenburn-bg-05)))) + + `(menu ((t (:foreground ,azenburn-fg :background ,azenburn-bg)))) + `(minibuffer-prompt ((t (:foreground ,azenburn-dark-blue)))) + `(mode-line + ((,class (:foreground ,azenburn-violet+1 + :background ,azenburn-bg-1 + :box (:line-width -1 :style released-button))) + (t :inverse-video t))) + `(mode-line-buffer-id ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(mode-line-inactive + ((t (:foreground ,azenburn-violet-1 + :background ,azenburn-bg-05 + :box (:line-width -1 :style released-button))))) + `(region ((,class (:background "#d4d4d4")) + (t :inverse-video t))) + `(secondary-selection ((t (:background ,azenburn-bg+2)))) + `(trailing-whitespace ((t (:background ,azenburn-blue)))) + `(vertical-border ((t (:foreground ,azenburn-fg)))) + + ;;; font lock + `(font-lock-builtin-face ((t (:foreground ,azenburn-bordeaux)))) + `(font-lock-comment-face ((t (:foreground ,azenburn-violet)))) + `(font-lock-comment-delimiter-face ((t (:foreground ,azenburn-violet)))) + `(font-lock-constant-face ((t (:foreground ,azenburn-violet+4)))) + `(font-lock-doc-face ((t (:foreground ,azenburn-violet+1)))) + `(font-lock-doc-string-face ((t (:foreground ,azenburn-beige-2)))) + `(font-lock-function-name-face ((t (:foreground ,azenburn-beige)))) + `(font-lock-keyword-face ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(font-lock-negation-char-face ((t (:foreground ,azenburn-fg)))) + `(font-lock-preprocessor-face ((t (:foreground ,azenburn-beige+1)))) + `(font-lock-string-face ((t (:foreground ,azenburn-blue)))) + `(font-lock-type-face ((t (:foreground ,azenburn-beige-1)))) + `(font-lock-variable-name-face ((t (:foreground ,azenburn-light-blue)))) + `(font-lock-warning-face ((t (:foreground ,azenburn-dark-blue-2 :weight bold)))) + + `(c-annotation-face ((t (:inherit font-lock-constant-face)))) + + ;;; newsticker + `(newsticker-date-face ((t (:foreground ,azenburn-fg)))) + `(newsticker-default-face ((t (:foreground ,azenburn-fg)))) + `(newsticker-enclosure-face ((t (:foreground ,azenburn-violet+3)))) + `(newsticker-extra-face ((t (:foreground ,azenburn-bg+2 :height 0.8)))) + `(newsticker-feed-face ((t (:foreground ,azenburn-fg)))) + `(newsticker-immortal-item-face ((t (:foreground ,azenburn-violet)))) + `(newsticker-new-item-face ((t (:foreground ,azenburn-beige)))) + `(newsticker-obsolete-item-face ((t (:foreground ,azenburn-blue)))) + `(newsticker-old-item-face ((t (:foreground ,azenburn-bg+3)))) + `(newsticker-statistics-face ((t (:foreground ,azenburn-fg)))) + `(newsticker-treeview-face ((t (:foreground ,azenburn-fg)))) + `(newsticker-treeview-immortal-face ((t (:foreground ,azenburn-violet)))) + `(newsticker-treeview-listwindow-face ((t (:foreground ,azenburn-fg)))) + `(newsticker-treeview-new-face ((t (:foreground ,azenburn-beige :weight bold)))) + `(newsticker-treeview-obsolete-face ((t (:foreground ,azenburn-blue)))) + `(newsticker-treeview-old-face ((t (:foreground ,azenburn-bg+3)))) + `(newsticker-treeview-selection-face ((t (:foreground ,azenburn-dark-blue)))) + + ;;; external + `(ace-jump-face-background + ((t (:foreground ,azenburn-fg-1 :background ,azenburn-bg :inverse-video nil)))) + `(ace-jump-face-foreground + ((t (:foreground ,azenburn-violet+2 :background ,azenburn-bg :inverse-video nil)))) + + ;; full-ack + `(ack-separator ((t (:foreground ,azenburn-fg)))) + `(ack-file ((t (:foreground ,azenburn-beige)))) + `(ack-line ((t (:foreground ,azenburn-dark-blue)))) + `(ack-match ((t (:foreground ,azenburn-light-blue :background ,azenburn-bg-1 :weight bold)))) + + ;; auctex + `(font-latex-bold ((t (:inherit bold)))) + `(font-latex-warning ((t (:inherit font-lock-warning)))) + `(font-latex-sedate ((t (:foreground ,azenburn-dark-blue :weight bold )))) + `(font-latex-title-4 ((t (:inherit variable-pitch :weight bold)))) + + ;; auto-complete + `(ac-candidate-face ((t (:background ,azenburn-bg+3 :foreground "white")))) + `(ac-selection-face ((t (:background ,azenburn-beige-4 :foreground ,azenburn-fg)))) + `(popup-tip-face ((t (:background ,azenburn-dark-blue-2 :foreground "white")))) + `(popup-scroll-bar-foreground-face ((t (:background ,azenburn-beige-5)))) + `(popup-scroll-bar-background-face ((t (:background ,azenburn-bg-1)))) + `(popup-isearch-match ((t (:background ,azenburn-bg :foreground ,azenburn-fg)))) + + ;; android mode + `(android-mode-debug-face ((t (:foreground ,azenburn-violet+1)))) + `(android-mode-error-face ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(android-mode-info-face ((t (:foreground ,azenburn-fg)))) + `(android-mode-verbose-face ((t (:foreground ,azenburn-violet)))) + `(android-mode-warning-face ((t (:foreground ,azenburn-dark-blue)))) + + ;; bm + `(bm-face ((t (:background ,azenburn-dark-blue-1 :foreground ,azenburn-bg)))) + `(bm-fringe-face ((t (:background ,azenburn-dark-blue-1 :foreground ,azenburn-bg)))) + `(bm-fringe-persistent-face ((t (:background ,azenburn-violet-1 :foreground ,azenburn-bg)))) + `(bm-persistent-face ((t (:background ,azenburn-violet-1 :foreground ,azenburn-bg)))) + + ;; clojure-test-mode + `(clojure-test-failure-face ((t (:foreground ,azenburn-light-blue :weight bold :underline t)))) + `(clojure-test-error-face ((t (:foreground ,azenburn-blue :weight bold :underline t)))) + `(clojure-test-success-face ((t (:foreground ,azenburn-violet+1 :weight bold :underline t)))) + + ;; ctable + `(ctbl:face-cell-select ((t (:background ,azenburn-beige :foreground ,azenburn-bg)))) + `(ctbl:face-continue-bar ((t (:background ,azenburn-bg-05 :foreground ,azenburn-bg)))) + `(ctbl:face-row-select ((t (:background ,azenburn-bordeaux :foreground ,azenburn-bg)))) + + ;; diff + `(diff-added ((,class (:foreground ,azenburn-violet+4 :background nil)) + (t (:foreground ,azenburn-violet+1 :background nil)))) + `(diff-changed ((t (:foreground ,azenburn-dark-blue)))) + `(diff-removed ((,class (:foreground ,azenburn-blue :background nil)) + (t (:foreground ,azenburn-blue-3 :background nil)))) + `(diff-refine-added ((t :inherit diff-added :weight bold))) + `(diff-refine-change ((t :inherit diff-changed :weight bold))) + `(diff-refine-removed ((t :inherit diff-removed :weight bold))) + `(diff-header ((,class (:background ,azenburn-bg+2)) + (t (:background ,azenburn-fg :foreground ,azenburn-bg)))) + `(diff-file-header + ((,class (:background ,azenburn-bg+2 :foreground ,azenburn-fg :bold t)) + (t (:background ,azenburn-fg :foreground ,azenburn-bg :bold t)))) + + ;; dired+ + `(diredp-display-msg ((t (:foreground ,azenburn-beige)))) + `(diredp-compressed-file-suffix ((t (:foreground ,azenburn-light-blue)))) + `(diredp-date-time ((t (:foreground ,azenburn-green)))) + `(diredp-deletion ((t (:foreground ,azenburn-dark-blue)))) + `(diredp-deletion-file-name ((t (:foreground ,azenburn-blue)))) + `(diredp-dir-heading ((t (:foreground ,azenburn-beige :background ,azenburn-bg-1)))) + `(diredp-dir-priv ((t (:foreground ,azenburn-bordeaux)))) + `(diredp-exec-priv ((t (:foreground ,azenburn-blue)))) + `(diredp-executable-tag ((t (:foreground ,azenburn-violet+1)))) + `(diredp-file-name ((t (:foreground ,azenburn-beige)))) + `(diredp-file-suffix ((t (:foreground ,azenburn-violet)))) + `(diredp-flag-mark ((t (:foreground ,azenburn-dark-blue)))) + `(diredp-flag-mark-line ((t (:foreground ,azenburn-light-blue)))) + `(diredp-ignored-file-name ((t (:foreground ,azenburn-blue)))) + `(diredp-link-priv ((t (:foreground ,azenburn-dark-blue)))) + `(diredp-mode-line-flagged ((t (:foreground ,azenburn-dark-blue)))) + `(diredp-mode-line-marked ((t (:foreground ,azenburn-light-blue)))) + `(diredp-no-priv ((t (:foreground ,azenburn-fg)))) + `(diredp-number ((t (:foreground ,azenburn-violet+1)))) + `(diredp-other-priv ((t (:foreground ,azenburn-dark-blue-1)))) + `(diredp-rare-priv ((t (:foreground ,azenburn-blue-1)))) + `(diredp-read-priv ((t (:foreground ,azenburn-violet-1)))) + `(diredp-symlink ((t (:foreground ,azenburn-dark-blue)))) + `(diredp-write-priv ((t (:foreground ,azenburn-green)))) + + ;; ert + `(ert-test-result-expected ((t (:foreground ,azenburn-violet+4 :background ,azenburn-bg)))) + `(ert-test-result-unexpected ((t (:foreground ,azenburn-blue :background ,azenburn-bg)))) + + ;; eshell + `(eshell-prompt ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(eshell-ls-archive ((t (:foreground ,azenburn-blue-1 :weight bold)))) + `(eshell-ls-backup ((t (:inherit font-lock-comment)))) + `(eshell-ls-clutter ((t (:inherit font-lock-comment)))) + `(eshell-ls-directory ((t (:foreground ,azenburn-beige+1 :weight bold)))) + `(eshell-ls-executable ((t (:foreground ,azenburn-blue+1 :weight bold)))) + `(eshell-ls-unreadable ((t (:foreground ,azenburn-fg)))) + `(eshell-ls-missing ((t (:inherit font-lock-warning)))) + `(eshell-ls-product ((t (:inherit font-lock-doc)))) + `(eshell-ls-special ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(eshell-ls-symlink ((t (:foreground ,azenburn-bordeaux :weight bold)))) + + ;; flycheck + `(flycheck-error-face ((t (:foreground ,azenburn-blue-1 :weight bold :underline t)))) + `(flycheck-warning-face ((t (:foreground ,azenburn-light-blue :weight bold :underline t)))) + + ;; flymake + `(flymake-errline ((t (:foreground ,azenburn-blue-1 :weight bold :underline t)))) + `(flymake-warnline ((t (:foreground ,azenburn-light-blue :weight bold :underline t)))) + + ;; flyspell + `(flyspell-duplicate ((t (:foreground ,azenburn-light-blue :weight bold :underline t)))) + `(flyspell-incorrect ((t (:foreground ,azenburn-blue-1 :weight bold :underline t)))) + + ;; erc + `(erc-action-face ((t (:inherit erc-default-face)))) + `(erc-bold-face ((t (:weight bold)))) + `(erc-current-nick-face ((t (:foreground ,azenburn-beige :weight bold)))) + `(erc-dangerous-host-face ((t (:inherit font-lock-warning)))) + `(erc-default-face ((t (:foreground ,azenburn-fg)))) + `(erc-direct-msg-face ((t (:inherit erc-default)))) + `(erc-error-face ((t (:inherit font-lock-warning)))) + `(erc-fool-face ((t (:inherit erc-default)))) + `(erc-highlight-face ((t (:inherit hover-highlight)))) + `(erc-input-face ((t (:foreground ,azenburn-dark-blue)))) + `(erc-keyword-face ((t (:foreground ,azenburn-beige :weight bold)))) + `(erc-nick-default-face ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(erc-my-nick-face ((t (:foreground ,azenburn-blue :weight bold)))) + `(erc-nick-msg-face ((t (:inherit erc-default)))) + `(erc-notice-face ((t (:foreground ,azenburn-violet)))) + `(erc-pal-face ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(erc-prompt-face ((t (:foreground ,azenburn-light-blue :background ,azenburn-bg :weight bold)))) + `(erc-timestamp-face ((t (:foreground ,azenburn-violet+1)))) + `(erc-underline-face ((t (:underline t)))) + + ;; git-gutter + `(git-gutter:added ((t (:foreground ,azenburn-violet :weight bold :inverse-video t)))) + `(git-gutter:deleted ((t (:foreground ,azenburn-blue :weight bold :inverse-video t)))) + `(git-gutter:modified ((t (:foreground ,azenburn-green :weight bold :inverse-video t)))) + `(git-gutter:unchanged ((t (:foreground ,azenburn-fg :weight bold :inverse-video t)))) + + ;; git-gutter-fr + `(git-gutter-fr:added ((t (:foreground ,azenburn-violet :weight bold)))) + `(git-gutter-fr:deleted ((t (:foreground ,azenburn-blue :weight bold)))) + `(git-gutter-fr:modified ((t (:foreground ,azenburn-green :weight bold)))) + + ;; gnus + `(gnus-group-mail-1 ((t (:bold t :inherit gnus-group-mail-1-empty)))) + `(gnus-group-mail-1-empty ((t (:inherit gnus-group-news-1-empty)))) + `(gnus-group-mail-2 ((t (:bold t :inherit gnus-group-mail-2-empty)))) + `(gnus-group-mail-2-empty ((t (:inherit gnus-group-news-2-empty)))) + `(gnus-group-mail-3 ((t (:bold t :inherit gnus-group-mail-3-empty)))) + `(gnus-group-mail-3-empty ((t (:inherit gnus-group-news-3-empty)))) + `(gnus-group-mail-4 ((t (:bold t :inherit gnus-group-mail-4-empty)))) + `(gnus-group-mail-4-empty ((t (:inherit gnus-group-news-4-empty)))) + `(gnus-group-mail-5 ((t (:bold t :inherit gnus-group-mail-5-empty)))) + `(gnus-group-mail-5-empty ((t (:inherit gnus-group-news-5-empty)))) + `(gnus-group-mail-6 ((t (:bold t :inherit gnus-group-mail-6-empty)))) + `(gnus-group-mail-6-empty ((t (:inherit gnus-group-news-6-empty)))) + `(gnus-group-mail-low ((t (:bold t :inherit gnus-group-mail-low-empty)))) + `(gnus-group-mail-low-empty ((t (:inherit gnus-group-news-low-empty)))) + `(gnus-group-news-1 ((t (:bold t :inherit gnus-group-news-1-empty)))) + `(gnus-group-news-2 ((t (:bold t :inherit gnus-group-news-2-empty)))) + `(gnus-group-news-3 ((t (:bold t :inherit gnus-group-news-3-empty)))) + `(gnus-group-news-4 ((t (:bold t :inherit gnus-group-news-4-empty)))) + `(gnus-group-news-5 ((t (:bold t :inherit gnus-group-news-5-empty)))) + `(gnus-group-news-6 ((t (:bold t :inherit gnus-group-news-6-empty)))) + `(gnus-group-news-low ((t (:bold t :inherit gnus-group-news-low-empty)))) + `(gnus-header-content ((t (:inherit message-header-other)))) + `(gnus-header-from ((t (:inherit message-header-from)))) + `(gnus-header-name ((t (:inherit message-header-name)))) + `(gnus-header-newsgroups ((t (:inherit message-header-other)))) + `(gnus-header-subject ((t (:inherit message-header-subject)))) + `(gnus-summary-cancelled ((t (:foreground ,azenburn-light-blue)))) + `(gnus-summary-high-ancient ((t (:foreground ,azenburn-beige)))) + `(gnus-summary-high-read ((t (:foreground ,azenburn-violet :weight bold)))) + `(gnus-summary-high-ticked ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(gnus-summary-high-unread ((t (:foreground ,azenburn-fg :weight bold)))) + `(gnus-summary-low-ancient ((t (:foreground ,azenburn-beige)))) + `(gnus-summary-low-read ((t (:foreground ,azenburn-violet)))) + `(gnus-summary-low-ticked ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(gnus-summary-low-unread ((t (:foreground ,azenburn-fg)))) + `(gnus-summary-normal-ancient ((t (:foreground ,azenburn-beige)))) + `(gnus-summary-normal-read ((t (:foreground ,azenburn-violet)))) + `(gnus-summary-normal-ticked ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(gnus-summary-normal-unread ((t (:foreground ,azenburn-fg)))) + `(gnus-summary-selected ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(gnus-cite-1 ((t (:foreground ,azenburn-beige)))) + `(gnus-cite-10 ((t (:foreground ,azenburn-dark-blue-1)))) + `(gnus-cite-11 ((t (:foreground ,azenburn-dark-blue)))) + `(gnus-cite-2 ((t (:foreground ,azenburn-beige-1)))) + `(gnus-cite-3 ((t (:foreground ,azenburn-beige-2)))) + `(gnus-cite-4 ((t (:foreground ,azenburn-violet+2)))) + `(gnus-cite-5 ((t (:foreground ,azenburn-violet+1)))) + `(gnus-cite-6 ((t (:foreground ,azenburn-violet)))) + `(gnus-cite-7 ((t (:foreground ,azenburn-blue)))) + `(gnus-cite-8 ((t (:foreground ,azenburn-blue-1)))) + `(gnus-cite-9 ((t (:foreground ,azenburn-blue-2)))) + `(gnus-group-news-1-empty ((t (:foreground ,azenburn-dark-blue)))) + `(gnus-group-news-2-empty ((t (:foreground ,azenburn-violet+3)))) + `(gnus-group-news-3-empty ((t (:foreground ,azenburn-violet+1)))) + `(gnus-group-news-4-empty ((t (:foreground ,azenburn-beige-2)))) + `(gnus-group-news-5-empty ((t (:foreground ,azenburn-beige-3)))) + `(gnus-group-news-6-empty ((t (:foreground ,azenburn-bg+2)))) + `(gnus-group-news-low-empty ((t (:foreground ,azenburn-bg+2)))) + `(gnus-signature ((t (:foreground ,azenburn-dark-blue)))) + `(gnus-x ((t (:background ,azenburn-fg :foreground ,azenburn-bg)))) + + ;; guide-key + `(guide-key/highlight-command-face ((t (:foreground ,azenburn-beige)))) + `(guide-key/key-face ((t (:foreground ,azenburn-violet)))) + `(guide-key/prefix-command-face ((t (:foreground ,azenburn-violet+1)))) + + ;; helm + `(helm-header + ((t (:foreground ,azenburn-violet + :background ,azenburn-bg + :underline nil + :box nil)))) + `(helm-source-header + ((t (:foreground ,azenburn-dark-blue + :background ,azenburn-bg-1 + :underline nil + :weight bold + :box (:line-width -1 :style released-button))))) + `(helm-selection ((t (:background ,azenburn-bg+1 :underline nil)))) + `(helm-selection-line ((t (:background ,azenburn-bg+1)))) + `(helm-visible-mark ((t (:foreground ,azenburn-bg :background ,azenburn-dark-blue-2)))) + `(helm-candidate-number ((t (:foreground ,azenburn-violet+4 :background ,azenburn-bg-1)))) + `(helm-ff-directory ((t (:foreground ,azenburn-green)))) + + ;; hl-line-mode + `(hl-line-face ((,class (:background "#f4f4f4")) + (t :weight bold))) + `(hl-line ((,class (:background "#f4f4f4")) ; old emacsen + (t :weight bold))) + + ;; hl-sexp + `(hl-sexp-face ((,class (:background ,azenburn-bg+1)) + (t :weight bold))) + + ;; ido-mode + `(ido-first-match ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(ido-only-match ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(ido-subdir ((t (:foreground ,azenburn-dark-blue)))) + + ;; js2-mode + `(js2-warning-face ((t (:underline ,azenburn-light-blue)))) + `(js2-error-face ((t (:foreground ,azenburn-blue :weight bold)))) + `(js2-jsdoc-tag-face ((t (:foreground ,azenburn-violet-1)))) + `(js2-jsdoc-type-face ((t (:foreground ,azenburn-violet+2)))) + `(js2-jsdoc-value-face ((t (:foreground ,azenburn-violet+3)))) + `(js2-function-param-face ((t (:foreground, azenburn-violet+3)))) + `(js2-external-variable-face ((t (:foreground "#ff0000")))) + + ;; jabber-mode + `(jabber-roster-user-away ((t (:foreground ,azenburn-violet+2)))) + `(jabber-roster-user-online ((t (:foreground ,azenburn-beige-1)))) + `(jabber-roster-user-dnd ((t (:foreground ,azenburn-blue+1)))) + `(jabber-rare-time-face ((t (:foreground ,azenburn-violet+1)))) + `(jabber-chat-prompt-local ((t (:foreground ,azenburn-beige-1)))) + `(jabber-chat-prompt-foreign ((t (:foreground ,azenburn-blue+1)))) + `(jabber-activity-face((t (:foreground ,azenburn-blue+1)))) + `(jabber-activity-personal-face ((t (:foreground ,azenburn-beige+1)))) + `(jabber-title-small ((t (:height 1.1 :weight bold)))) + `(jabber-title-medium ((t (:height 1.2 :weight bold)))) + `(jabber-title-large ((t (:height 1.3 :weight bold)))) + + ;; linum-mode + `(linum ((t (:foreground ,azenburn-violet+2 :background "#f0f0f0")))) + + ;; macrostep + `(macrostep-gensym-1 + ((t (:foreground ,azenburn-violet+2 :background ,azenburn-bg-1)))) + `(macrostep-gensym-2 + ((t (:foreground ,azenburn-blue+1 :background ,azenburn-bg-1)))) + `(macrostep-gensym-3 + ((t (:foreground ,azenburn-beige+1 :background ,azenburn-bg-1)))) + `(macrostep-gensym-4 + ((t (:foreground ,azenburn-green :background ,azenburn-bg-1)))) + `(macrostep-gensym-5 + ((t (:foreground ,azenburn-dark-blue :background ,azenburn-bg-1)))) + `(macrostep-expansion-highlight-face + ((t (:inherit highlight)))) + `(macrostep-macro-face + ((t (:underline t)))) + + ;; magit + `(magit-section-title ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(magit-branch ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(magit-item-highlight ((t (:background ,azenburn-bg+1)))) + + ;; egg + `(egg-text-base ((t (:foreground ,azenburn-fg)))) + `(egg-help-header-1 ((t (:foreground ,azenburn-dark-blue)))) + `(egg-help-header-2 ((t (:foreground ,azenburn-violet+3)))) + `(egg-branch ((t (:foreground ,azenburn-dark-blue)))) + `(egg-branch-mono ((t (:foreground ,azenburn-dark-blue)))) + `(egg-term ((t (:foreground ,azenburn-dark-blue)))) + `(egg-diff-add ((t (:foreground ,azenburn-violet+4)))) + `(egg-diff-del ((t (:foreground ,azenburn-blue+1)))) + `(egg-diff-file-header ((t (:foreground ,azenburn-dark-blue-2)))) + `(egg-section-title ((t (:foreground ,azenburn-dark-blue)))) + `(egg-stash-mono ((t (:foreground ,azenburn-violet+4)))) + + ;; message-mode + `(message-cited-text ((t (:inherit font-lock-comment)))) + `(message-header-name ((t (:foreground ,azenburn-violet+1)))) + `(message-header-other ((t (:foreground ,azenburn-violet)))) + `(message-header-to ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(message-header-from ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(message-header-cc ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(message-header-newsgroups ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(message-header-subject ((t (:foreground ,azenburn-light-blue :weight bold)))) + `(message-header-xheader ((t (:foreground ,azenburn-violet)))) + `(message-mml ((t (:foreground ,azenburn-dark-blue :weight bold)))) + `(message-separator ((t (:inherit font-lock-comment)))) + + ;; mew + `(mew-face-header-subject ((t (:foreground ,azenburn-light-blue)))) + `(mew-face-header-from ((t (:foreground ,azenburn-dark-blue)))) + `(mew-face-header-date ((t (:foreground ,azenburn-violet)))) + `(mew-face-header-to ((t (:foreground ,azenburn-blue)))) + `(mew-face-header-key ((t (:foreground ,azenburn-violet)))) + `(mew-face-header-private ((t (:foreground ,azenburn-violet)))) + `(mew-face-header-important ((t (:foreground ,azenburn-beige)))) + `(mew-face-header-marginal ((t (:foreground ,azenburn-fg :weight bold)))) + `(mew-face-header-warning ((t (:foreground ,azenburn-blue)))) + `(mew-face-header-xmew ((t (:foreground ,azenburn-violet)))) + `(mew-face-header-xmew-bad ((t (:foreground ,azenburn-blue)))) + `(mew-face-body-url ((t (:foreground ,azenburn-light-blue)))) + `(mew-face-body-comment ((t (:foreground ,azenburn-fg :slant italic)))) + `(mew-face-body-cite1 ((t (:foreground ,azenburn-violet)))) + `(mew-face-body-cite2 ((t (:foreground ,azenburn-beige)))) + `(mew-face-body-cite3 ((t (:foreground ,azenburn-light-blue)))) + `(mew-face-body-cite4 ((t (:foreground ,azenburn-dark-blue)))) + `(mew-face-body-cite5 ((t (:foreground ,azenburn-blue)))) + `(mew-face-mark-review ((t (:foreground ,azenburn-beige)))) + `(mew-face-mark-escape ((t (:foreground ,azenburn-violet)))) + `(mew-face-mark-delete ((t (:foreground ,azenburn-blue)))) + `(mew-face-mark-unlink ((t (:foreground ,azenburn-dark-blue)))) + `(mew-face-mark-refile ((t (:foreground ,azenburn-violet)))) + `(mew-face-mark-unread ((t (:foreground ,azenburn-blue-2)))) + `(mew-face-eof-message ((t (:foreground ,azenburn-violet)))) + `(mew-face-eof-part ((t (:foreground ,azenburn-dark-blue)))) + + ;; mic-paren + `(paren-face-match ((t (:foreground ,azenburn-bordeaux :background ,azenburn-bg :weight bold)))) + `(paren-face-mismatch ((t (:foreground ,azenburn-bg :background ,azenburn-green :weight bold)))) + `(paren-face-no-match ((t (:foreground ,azenburn-bg :background ,azenburn-blue :weight bold)))) + + ;; mingus + `(mingus-directory-face ((t (:foreground ,azenburn-beige)))) + `(mingus-pausing-face ((t (:foreground ,azenburn-green)))) + `(mingus-playing-face ((t (:foreground ,azenburn-bordeaux)))) + `(mingus-playlist-face ((t (:foreground ,azenburn-bordeaux )))) + `(mingus-song-file-face ((t (:foreground ,azenburn-dark-blue)))) + `(mingus-stopped-face ((t (:foreground ,azenburn-blue)))) + + ;; nav + `(nav-face-heading ((t (:foreground ,azenburn-dark-blue)))) + `(nav-face-button-num ((t (:foreground ,azenburn-bordeaux)))) + `(nav-face-dir ((t (:foreground ,azenburn-violet)))) + `(nav-face-hdir ((t (:foreground ,azenburn-blue)))) + `(nav-face-file ((t (:foreground ,azenburn-fg)))) + `(nav-face-hfile ((t (:foreground ,azenburn-blue-4)))) + + ;; mu4e + `(mu4e-cited-1-face ((t (:foreground ,azenburn-beige :slant italic)))) + `(mu4e-cited-2-face ((t (:foreground ,azenburn-violet+2 :slant italic)))) + `(mu4e-cited-3-face ((t (:foreground ,azenburn-beige-2 :slant italic)))) + `(mu4e-cited-4-face ((t (:foreground ,azenburn-violet :slant italic)))) + `(mu4e-cited-5-face ((t (:foreground ,azenburn-beige-4 :slant italic)))) + `(mu4e-cited-6-face ((t (:foreground ,azenburn-violet-1 :slant italic)))) + `(mu4e-cited-7-face ((t (:foreground ,azenburn-beige :slant italic)))) + `(mu4e-replied-face ((t (:foreground ,azenburn-bg+3)))) + `(mu4e-trashed-face ((t (:foreground ,azenburn-bg+3 :strike-through t)))) + + ;; mumamo + `(mumamo-background-chunk-major ((t (:background nil)))) + `(mumamo-background-chunk-submode1 ((t (:background ,azenburn-bg-1)))) + `(mumamo-background-chunk-submode2 ((t (:background ,azenburn-bg+2)))) + `(mumamo-background-chunk-submode3 ((t (:background ,azenburn-bg+3)))) + `(mumamo-background-chunk-submode4 ((t (:background ,azenburn-bg+1)))) + + ;; org-mode + `(org-agenda-date-today + ((t (:foreground "black" :slant italic :weight bold))) t) + `(org-agenda-structure + ((t (:inherit font-lock-comment-face)))) + `(org-archived ((t (:foreground ,azenburn-fg :weight bold)))) + `(org-checkbox ((t (:background ,azenburn-bg+2 :foreground "black" + :box (:line-width 1 :style released-button))))) + `(org-date ((t (:foreground ,azenburn-beige :underline t)))) + `(org-deadline-announce ((t (:foreground ,azenburn-blue-1)))) + `(org-done ((t (:bold t :weight bold :foreground ,azenburn-violet+3)))) + `(org-formula ((t (:foreground ,azenburn-dark-blue-2)))) + `(org-headline-done ((t (:foreground ,azenburn-violet+3)))) + `(org-hide ((t (:foreground ,azenburn-bg-1)))) + `(org-level-1 ((t (:foreground ,azenburn-light-blue)))) + `(org-level-2 ((t (:foreground ,azenburn-violet+4)))) + `(org-level-3 ((t (:foreground ,azenburn-beige-1)))) + `(org-level-4 ((t (:foreground ,azenburn-dark-blue-2)))) + `(org-level-5 ((t (:foreground ,azenburn-bordeaux)))) + `(org-level-6 ((t (:foreground ,azenburn-violet+2)))) + `(org-level-7 ((t (:foreground ,azenburn-blue-4)))) + `(org-level-8 ((t (:foreground ,azenburn-beige-4)))) + `(org-link ((t (:foreground ,azenburn-dark-blue-2 :underline t)))) + `(org-scheduled ((t (:foreground ,azenburn-violet+4)))) + `(org-scheduled-previously ((t (:foreground ,azenburn-blue-4)))) + `(org-scheduled-today ((t (:foreground ,azenburn-beige+1)))) + `(org-special-keyword ((t (:foreground ,azenburn-fg-1 :weight normal)))) + `(org-table ((t (:foreground ,azenburn-violet+2)))) + `(org-tag ((t (:bold t :weight bold)))) + `(org-time-grid ((t (:foreground ,azenburn-light-blue)))) + `(org-todo ((t (:bold t :foreground ,azenburn-blue :weight bold)))) + `(org-upcoming-deadline ((t (:inherit font-lock-keyword-face)))) + `(org-warning ((t (:bold t :foreground ,azenburn-blue :weight bold :underline nil)))) + `(org-column ((t (:background ,azenburn-bg-1)))) + `(org-column-title ((t (:background ,azenburn-bg-1 :underline t :weight bold)))) + + ;; outline + `(outline-1 ((t (:foreground ,azenburn-light-blue)))) + `(outline-2 ((t (:foreground ,azenburn-violet+4)))) + `(outline-3 ((t (:foreground ,azenburn-beige-1)))) + `(outline-4 ((t (:foreground ,azenburn-dark-blue-2)))) + `(outline-5 ((t (:foreground ,azenburn-bordeaux)))) + `(outline-6 ((t (:foreground ,azenburn-violet+2)))) + `(outline-7 ((t (:foreground ,azenburn-blue-4)))) + `(outline-8 ((t (:foreground ,azenburn-beige-4)))) + + ;; rainbow-delimiters + `(rainbow-delimiters-depth-1-face ((t (:foreground ,azenburn-fg)))) + `(rainbow-delimiters-depth-2-face ((t (:foreground ,azenburn-violet+2)))) + `(rainbow-delimiters-depth-3-face ((t (:foreground ,azenburn-dark-blue-2)))) + `(rainbow-delimiters-depth-4-face ((t (:foreground ,azenburn-bordeaux)))) + `(rainbow-delimiters-depth-5-face ((t (:foreground ,azenburn-violet-1)))) + `(rainbow-delimiters-depth-6-face ((t (:foreground ,azenburn-beige+1)))) + `(rainbow-delimiters-depth-7-face ((t (:foreground ,azenburn-dark-blue-1)))) + `(rainbow-delimiters-depth-8-face ((t (:foreground ,azenburn-violet+1)))) + `(rainbow-delimiters-depth-9-face ((t (:foreground ,azenburn-beige-2)))) + `(rainbow-delimiters-depth-10-face ((t (:foreground ,azenburn-light-blue)))) + `(rainbow-delimiters-depth-11-face ((t (:foreground ,azenburn-violet)))) + `( rainbow-delimiters-depth-12-face ((t (:foreground ,azenburn-beige-5)))) + + ;;rcirc + `(rcirc-my-nick ((t (:foreground ,azenburn-beige)))) + `(rcirc-other-nick ((t (:foreground ,azenburn-light-blue)))) + `(rcirc-bright-nick ((t (:foreground ,azenburn-beige+1)))) + `(rcirc-dim-nick ((t (:foreground ,azenburn-beige-2)))) + `(rcirc-server ((t (:foreground ,azenburn-violet)))) + `(rcirc-server-prefix ((t (:foreground ,azenburn-violet+1)))) + `(rcirc-timestamp ((t (:foreground ,azenburn-violet+2)))) + `(rcirc-nick-in-message ((t (:foreground ,azenburn-dark-blue)))) + `(rcirc-nick-in-message-full-line ((t (:bold t)))) + `(rcirc-prompt ((t (:foreground ,azenburn-dark-blue :bold t)))) + `(rcirc-track-nick ((t (:inverse-video t)))) + `(rcirc-track-keyword ((t (:bold t)))) + `(rcirc-url ((t (:bold t)))) + `(rcirc-keyword ((t (:foreground ,azenburn-dark-blue :bold t)))) + + ;; rpm-mode + `(rpm-spec-dir-face ((t (:foreground ,azenburn-violet)))) + `(rpm-spec-doc-face ((t (:foreground ,azenburn-violet)))) + `(rpm-spec-ghost-face ((t (:foreground ,azenburn-blue)))) + `(rpm-spec-macro-face ((t (:foreground ,azenburn-dark-blue)))) + `(rpm-spec-obsolete-tag-face ((t (:foreground ,azenburn-blue)))) + `(rpm-spec-package-face ((t (:foreground ,azenburn-blue)))) + `(rpm-spec-section-face ((t (:foreground ,azenburn-dark-blue)))) + `(rpm-spec-tag-face ((t (:foreground ,azenburn-beige)))) + `(rpm-spec-var-face ((t (:foreground ,azenburn-blue)))) + + ;; rst-mode + `(rst-level-1-face ((t (:foreground ,azenburn-light-blue)))) + `(rst-level-2-face ((t (:foreground ,azenburn-violet+1)))) + `(rst-level-3-face ((t (:foreground ,azenburn-beige-1)))) + `(rst-level-4-face ((t (:foreground ,azenburn-dark-blue-2)))) + `(rst-level-5-face ((t (:foreground ,azenburn-bordeaux)))) + `(rst-level-6-face ((t (:foreground ,azenburn-violet-1)))) + + ;; show-paren + `(show-paren-mismatch ((t (:foreground ,azenburn-blue-3 :background ,azenburn-bg :weight bold)))) + `(show-paren-match ((t (:foreground ,azenburn-beige-1 :background ,azenburn-bg :weight bold)))) + + ;; sml-mode-line + '(sml-modeline-end-face ((t :inherit default :width condensed))) + + ;; SLIME + `(slime-repl-inputed-output-face ((t (:foreground ,azenburn-blue)))) + + ;; tabbar + `(tabbar-button ((t (:foreground ,azenburn-fg + :background ,azenburn-bg)))) + `(tabbar-selected ((t (:foreground ,azenburn-fg + :background ,azenburn-bg + :box (:line-width -1 :style pressed-button))))) + `(tabbar-unselected ((t (:foreground ,azenburn-fg + :background ,azenburn-bg+1 + :box (:line-width -1 :style released-button))))) + + ;; term + `(term-color-black ((t (:foreground ,azenburn-bg + :background ,azenburn-bg-1)))) + `(term-color-red ((t (:foreground ,azenburn-blue-2 + :background ,azenburn-blue-4)))) + `(term-color-green ((t (:foreground ,azenburn-violet + :background ,azenburn-violet+2)))) + `(term-color-yellow ((t (:foreground ,azenburn-light-blue + :background ,azenburn-dark-blue)))) + `(term-color-blue ((t (:foreground ,azenburn-beige-1 + :background ,azenburn-beige-4)))) + `(term-color-magenta ((t (:foreground ,azenburn-green + :background ,azenburn-blue)))) + `(term-color-cyan ((t (:foreground ,azenburn-bordeaux + :background ,azenburn-beige)))) + `(term-color-white ((t (:foreground ,azenburn-fg + :background ,azenburn-fg-1)))) + '(term-default-fg-color ((t (:inherit term-color-white)))) + '(term-default-bg-color ((t (:inherit term-color-black)))) + + ;; volatile-highlights + `(vhl/default-face ((t (:background ,azenburn-bg-05)))) + + ;; emacs-w3m + `(w3m-anchor ((t (:foreground ,azenburn-dark-blue :underline t + :weight bold)))) + `(w3m-arrived-anchor ((t (:foreground ,azenburn-dark-blue-2 + :underline t :weight normal)))) + `(w3m-form ((t (:foreground ,azenburn-blue-1 :underline t)))) + `(w3m-header-line-location-title ((t (:foreground ,azenburn-dark-blue + :underline t :weight bold)))) + '(w3m-history-current-url ((t (:inherit match)))) + `(w3m-lnum ((t (:foreground ,azenburn-violet+2 :background ,azenburn-bg)))) + `(w3m-lnum-match ((t (:background ,azenburn-bg-1 + :foreground ,azenburn-light-blue + :weight bold)))) + `(w3m-lnum-minibuffer-prompt ((t (:foreground ,azenburn-dark-blue)))) + + ;; whitespace-mode + `(whitespace-space ((t (:background ,azenburn-bg+1 :foreground ,azenburn-bg+1)))) + `(whitespace-hspace ((t (:background ,azenburn-bg+1 :foreground ,azenburn-bg+1)))) + `(whitespace-tab ((t (:background ,azenburn-blue-1)))) + `(whitespace-newline ((t (:foreground ,azenburn-bg+1)))) + `(whitespace-trailing ((t (:background ,azenburn-blue)))) + `(whitespace-line ((t (:background ,azenburn-bg :foreground ,azenburn-green)))) + `(whitespace-space-before-tab ((t (:background ,azenburn-light-blue :foreground ,azenburn-light-blue)))) + `(whitespace-indentation ((t (:background ,azenburn-dark-blue :foreground ,azenburn-blue)))) + `(whitespace-empty ((t (:background ,azenburn-dark-blue)))) + `(whitespace-space-after-tab ((t (:background ,azenburn-dark-blue :foreground ,azenburn-blue)))) + + ;; wanderlust + `(wl-highlight-folder-few-face ((t (:foreground ,azenburn-blue-2)))) + `(wl-highlight-folder-many-face ((t (:foreground ,azenburn-blue-1)))) + `(wl-highlight-folder-path-face ((t (:foreground ,azenburn-light-blue)))) + `(wl-highlight-folder-unread-face ((t (:foreground ,azenburn-beige)))) + `(wl-highlight-folder-zero-face ((t (:foreground ,azenburn-fg)))) + `(wl-highlight-folder-unknown-face ((t (:foreground ,azenburn-beige)))) + `(wl-highlight-message-citation-header ((t (:foreground ,azenburn-blue-1)))) + `(wl-highlight-message-cited-text-1 ((t (:foreground ,azenburn-blue)))) + `(wl-highlight-message-cited-text-2 ((t (:foreground ,azenburn-violet+2)))) + `(wl-highlight-message-cited-text-3 ((t (:foreground ,azenburn-beige)))) + `(wl-highlight-message-cited-text-4 ((t (:foreground ,azenburn-beige+1)))) + `(wl-highlight-message-header-contents-face ((t (:foreground ,azenburn-violet)))) + `(wl-highlight-message-headers-face ((t (:foreground ,azenburn-blue+1)))) + `(wl-highlight-message-important-header-contents ((t (:foreground ,azenburn-violet+2)))) + `(wl-highlight-message-header-contents ((t (:foreground ,azenburn-violet+1)))) + `(wl-highlight-message-important-header-contents2 ((t (:foreground ,azenburn-violet+2)))) + `(wl-highlight-message-signature ((t (:foreground ,azenburn-violet)))) + `(wl-highlight-message-unimportant-header-contents ((t (:foreground ,azenburn-fg)))) + `(wl-highlight-summary-answered-face ((t (:foreground ,azenburn-beige)))) + `(wl-highlight-summary-disposed-face ((t (:foreground ,azenburn-fg + :slant italic)))) + `(wl-highlight-summary-new-face ((t (:foreground ,azenburn-beige)))) + `(wl-highlight-summary-normal-face ((t (:foreground ,azenburn-fg)))) + `(wl-highlight-summary-thread-top-face ((t (:foreground ,azenburn-dark-blue)))) + `(wl-highlight-thread-indent-face ((t (:foreground ,azenburn-green)))) + `(wl-highlight-summary-refiled-face ((t (:foreground ,azenburn-fg)))) + `(wl-highlight-summary-displaying-face ((t (:underline t :weight bold)))) + + ;; which-func-mode + `(which-func ((t (:foreground ,azenburn-violet+4)))) + + ;; yascroll + `(yascroll:thumb-text-area ((t (:background ,azenburn-bg-1)))) + `(yascroll:thumb-fringe ((t (:background ,azenburn-bg-1 :foreground ,azenburn-bg-1)))) + ) + + ;;; custom theme variables + (custom-theme-set-variables + 'prez + `(ansi-color-names-vector [,azenburn-bg ,azenburn-blue ,azenburn-violet + ,azenburn-dark-blue ,azenburn-beige + ,azenburn-green ,azenburn-bordeaux + ,azenburn-fg]) + + ;; fill-column-indicator + `(fci-rule-color ,azenburn-bg-05) + + ;; vc-annotate + `(vc-annotate-color-map + '(( 20. . ,azenburn-blue-1) + ( 40. . ,azenburn-blue) + ( 60. . ,azenburn-light-blue) + ( 80. . ,azenburn-dark-blue-2) + (100. . ,azenburn-dark-blue-1) + (120. . ,azenburn-dark-blue) + (140. . ,azenburn-violet-1) + (160. . ,azenburn-violet) + (180. . ,azenburn-violet+1) + (200. . ,azenburn-violet+2) + (220. . ,azenburn-violet+3) + (240. . ,azenburn-violet+4) + (260. . ,azenburn-bordeaux) + (280. . ,azenburn-beige-2) + (300. . ,azenburn-beige-1) + (320. . ,azenburn-beige) + (340. . ,azenburn-beige+1) + (360. . ,azenburn-green))) + `(vc-annotate-very-old-color ,azenburn-green) + `(vc-annotate-background ,azenburn-bg-1))) + +;;;###autoload +(and load-file-name + (boundp 'custom-theme-load-path) + (add-to-list 'custom-theme-load-path + (file-name-as-directory + (file-name-directory load-file-name)))) + +(provide-theme 'prez) + +;;; prez-theme.el ends here diff --git a/users/fimasvee/init.el b/users/fimasvee/init.el index 5f132cea9..8d0d1cdd3 100644 --- a/users/fimasvee/init.el +++ b/users/fimasvee/init.el @@ -2,31 +2,23 @@ (setq-default js2-basic-offset 2) (setq js-indent-level 2) -(setq expand-region-fast-keys-enabled nil) -(setq er--show-expansion-message t) - ;; Disallow scrolling with mouse wheel -(mouse-wheel-mode nil) +(when window-system + (mouse-wheel-mode -1)) + +;; Monday ftw +(set-variable 'calendar-week-start-day 1) ;; Font size (define-key global-map (kbd "M-s +") 'zoom-in) (define-key global-map (kbd "M-s -") 'zoom-out) -;; Experimental rebind of C-b and C-f -(fset 'quick-switch-buffer [?\C-x ?b return]) -(global-set-key (kbd "C-b") 'quick-switch-buffer) ;; toggle two most recent buffers -(global-set-key (kbd "C-f") 'duplicate-current-line-or-region) ;; duplicate line - -;; Experimental super on right command key. s-x is kill-region for instance. -(setq mac-right-command-modifier 'super) - -;; Edit in Chrome +;; No more scrolling surprises +(global-unset-key (kbd "C-v")) +(global-unset-key (kbd "M-v")) -(when (require 'edit-server nil t) - (edit-server-start)) - -(setq edit-server-url-major-mode-alist - '(("github\\.com" . markdown-mode))) +;; No graphics please o.O +(setq speedbar-use-images nil) ;; PHP (autoload 'php-mode "php-mode") @@ -36,29 +28,6 @@ (eval-after-load "php-mode" '(define-key php-mode-map (kbd "C-.") nil)) -;; Experimental: keep region when undoing in region -(defadvice undo-tree-undo (around keep-region activate) - (if (use-region-p) - (let ((m (set-marker (make-marker) (mark))) - (p (set-marker (make-marker) (point)))) - ad-do-it - (goto-char p) - (set-marker (mark-marker) m)) - ad-do-it)) - ;; Use GNU ls - install with: ;; brew install xz coreutils (setq insert-directory-program "gls") - -;; org-mode: beginning/end of buffer on M-up/down -(eval-after-load "org" - '(progn - (define-key org-mode-map (kbd "M-") 'beginning-of-buffer) - (define-key org-mode-map (kbd "M-") 'end-of-buffer) - (define-key org-mode-map (kbd "C-S-") 'org-metaup) - (define-key org-mode-map (kbd "C-S-") 'org-metadown))) - -;; Set to the location of your Org files on your local system -(setq org-directory "~/Dropbox/org") -(setq org-mobile-inbox-for-pull "~/Dropbox/org/flagged.org") -(setq org-mobile-directory "~/Dropbox/MobileOrg-staging") diff --git a/users/fimasvee/js2r-keys.el b/users/fimasvee/js2r-keys.el index dcead26c3..466ca0458 100644 --- a/users/fimasvee/js2r-keys.el +++ b/users/fimasvee/js2r-keys.el @@ -1,36 +1,9 @@ -(setq my-ctrl-option-mapping - '(("q" . "") - ("w" . "") - ("e" . "") - ("r" . "") - ("t" . "") - ("y" . "") - ("u" . "") - ("i" . "") - ("o" . "") - ("p" . "") - ("a" . "") - ("s" . "") - ("d" . "") - ("f" . "") - ("g" . "") - ("h" . "") - ("j" . "") - ("k" . "") - ("l" . "") - ("z" . "") - ("x" . "") - ("c" . "") - ("v" . "") - ("b" . "") - ("n" . "") - (" " . "") - ("3" . "M-£") - ("m" . ""))) +(require 'dash) +(require 's) (defun my-js2-keys (keys) (->> (string-to-list keys) - (--map (aget my-ctrl-option-mapping (char-to-string it))) + (--map (concat "C-s-" (char-to-string it))) (s-join " ") (read-kbd-macro))) @@ -62,11 +35,12 @@ (define-key js2-mode-map (my-js2-keys "jo") 'jump-between-source-and-test-files) (define-key js2-mode-map (my-js2-keys "oo") 'jump-between-source-and-test-files-other-window) (define-key js2-mode-map (my-js2-keys "ta") 'toggle-assert-refute) - (define-key js2-mode-map (my-js2-keys " " ) 'js2r-split-string) - )) + (define-key js2-mode-map (my-js2-keys "dp") 'js2r-duplicate-object-property-node) + (define-key js2-mode-map (my-js2-keys "lt") 'js2r-log-this) + (define-key js2-mode-map (kbd "C-s-SPC") 'js2r-split-string) + (define-key js2-mode-map (kbd "s-") 'js2r-forward-slurp) + (define-key js2-mode-map (kbd "s-") 'js2r-forward-barf) + + (define-key js2-mode-map (kbd "s-j") 'jump-between-source-and-test-files) -;; (f6 -;; (let* ((c (read-char "Char: ")) -;; (k (help-key-description (read-key-sequence "Describe key (or click or menu item): ") nil))) -;; (insert "(\"" c "\" . \"" k "\")") -;; (newline-and-indent))) + )) diff --git a/users/fimasvee/mu3e.el b/users/fimasvee/mu3e.el index cf9bf1e75..4cb4a7070 100644 --- a/users/fimasvee/mu3e.el +++ b/users/fimasvee/mu3e.el @@ -4,7 +4,9 @@ ;; Shortcuts (setq mu4e-maildir-shortcuts - '(("/gmail/inbox" . ?i))) + '(("/gmail/inbox" . ?i) + ("/todo" . ?t) + ("/readme" . ?r))) ;; sending mail (setq message-send-mail-function 'message-send-mail-with-sendmail diff --git a/users/fimasvee/my-defuns.el b/users/fimasvee/my-defuns.el index 6dd47161b..b265252f1 100644 --- a/users/fimasvee/my-defuns.el +++ b/users/fimasvee/my-defuns.el @@ -44,4 +44,16 @@ filename filename) t))) +(defun -flash-region (start end) + "Temporarily highlight region from START to END." + (let ((overlay (make-overlay start end))) + (overlay-put overlay 'face 'secondary-selection) + (overlay-put overlay 'priority 100) + (run-with-timer 0.2 nil 'delete-overlay overlay))) + +(defun js2r--flash-node (node) + (-flash-region (js2-node-abs-pos node) + (js2-node-abs-end node)) + (js2-node-short-name node)) + (provide 'my-defuns) diff --git a/users/fimasvee/project-mappings.el b/users/fimasvee/project-mappings.el index dd5a10552..1a209e854 100644 --- a/users/fimasvee/project-mappings.el +++ b/users/fimasvee/project-mappings.el @@ -1,15 +1,3 @@ -(defmacro project-specifics (name &rest body) - (declare (indent 1)) - `(progn - (add-hook 'find-file-hook - (lambda () - (when (string-match-p ,name (buffer-file-name)) - ,@body))) - (add-hook 'dired-after-readin-hook - (lambda () - (when (string-match-p ,name (dired-current-directory)) - ,@body))))) - ;; Intelliadv (defun custom-persp/intelliadv () @@ -29,7 +17,6 @@ (define-key persp-mode-map (kbd "C-x p r") 'custom-persp/emacsrocks) (project-specifics "projects/emacsrocks" - (set (make-local-variable 'slime-js-target-url) "http://localhost:4567/") (ffip-local-patterns "*.js" "*.scss" "*.org" "*.rb" "*.erb")) ;; zombietdd.com @@ -42,7 +29,6 @@ (define-key persp-mode-map (kbd "C-x p s") 'custom-persp/zombietdd.com) (project-specifics "projects/site-ztdd" - (set (make-local-variable 'slime-js-target-url) "http://localhost:4567/") (ffip-local-patterns "*.js" "*.scss" "*.org" "*.rb" "*.erb")) ;; Blockout @@ -55,8 +41,6 @@ (define-key persp-mode-map (kbd "C-x p bl") 'custom-persp/blockout) (project-specifics "projects/blockout" - (set (make-local-variable 'slime-js-target-url) "http://localhost:8000/") - (set (make-local-variable 'slime-js-browser-command) "open -a \"Google Chrome\"") (ffip-local-patterns "*.js" "*.css")) (add-hook 'js2-mode-hook @@ -69,6 +53,25 @@ (set (make-local-variable 'buster-test-prefix) "") (set (make-local-variable 'js2r-use-strict) t)))) +;; Oiiku + +(defun custom-persp/oiiku () + (interactive) + (custom-persp "oiiku" (find-file "~/projects/oiiku/"))) + +(define-key persp-mode-map (kbd "C-x p o") 'custom-persp/oiiku) + +(defun js2-oiiku-settings () + (when (string-match-p "projects/oiiku" (buffer-file-name)) + (setq js2-additional-externs '("angular" "cull" "dome" "app" "expect" "it" "inject" "beforeEach" "describe")) + (make-variable-buffer-local 'js2-basic-offset) + (setq js2-basic-offset 4))) + +(add-hook 'js2-mode-hook 'js2-oiiku-settings) + +(project-specifics "projects/oiiku" + (set (make-local-variable 'sgml-basic-offset) 2)) + ;; FINN Oppdrag (defun custom-persp/oppdrag () @@ -76,17 +79,47 @@ (custom-persp "oppdrag" (find-file "~/Dropbox/projects/finn-oppdrag/todo.org"))) -(define-key persp-mode-map (kbd "C-x p o") 'custom-persp/oppdrag) +;;(define-key persp-mode-map (kbd "C-x p o") 'custom-persp/oppdrag) (require 'oppdrag-mode) (project-specifics "oppdrag-services" - (set (make-local-variable 'slime-js-target-url) "http://local.finn.no:8080/") - (set (make-local-variable 'slime-js-connect-url) "http://local.finn.no:8009") - (set (make-local-variable 'slime-js-starting-url) "/oppdrag/") - (ffip-local-patterns "*.js" "*.jsp" "*.css" "*.org" "*.vm" "*jsTestDriver.conf" "*jawr.properties") + (make-local-variable 'grep-find-ignored-directories) + (add-to-list 'grep-find-ignored-directories "ckeditor") + (ffip-local-patterns "*.js" "*.tag" "*.jsp" "*.css" "*.org" "*.vm" "*jsTestDriver.conf" "*jawr.properties") (oppdrag-mode)) +;; FINN Reise + +(defun custom-persp/travel () + (interactive) + (custom-persp "travel" + (find-file "~/projects/finn-reise/travel-app/"))) + +(define-key persp-mode-map (kbd "C-x p t") 'custom-persp/travel) + +(require 'travel-mode) + +(add-hook 'js2-mode-hook + (lambda () + (when (string-match-p "travel-app" (buffer-file-name)) + (--each '("cull" "dome" "bane") (add-to-list 'js2-additional-externs it)) + (js2-fetch-autolint-externs "~/projects/finn-reise/travel-app/web/src/autolint.js") + (setq js2r-path-to-tests "/test/javascript/tests/") + (setq js2r-path-to-sources "/main/webapp/scripts/") + (setq js2r-test-suffix "Test") + (setq buster-default-global "FINN.travel") + (setq buster-add-default-global-to-iife t) + (setq buster-test-prefix "") + (set (make-local-variable 'js2-basic-offset) 4) + (set (make-local-variable 'buster-use-strict) t) + (set (make-local-variable 'js2r-use-strict) t)))) + +(project-specifics "travel-app" + (ffip-local-patterns "*.js" "*.tag" "*.jsp" "*.css" "*.org" "*.vm" "*jawr.properties") + (set (make-local-variable 'sgml-basic-offset) 2) + (travel-mode)) + ;; Zombie TDD (defun custom-persp/zombie () @@ -97,7 +130,6 @@ (define-key persp-mode-map (kbd "C-x p z") 'custom-persp/zombie) (project-specifics "projects/zombietdd" - (set (make-local-variable 'slime-js-target-url) "http://localhost:3000/") (ffip-local-patterns "*.js" "*.jade" "*.css" "*.json" "*.md")) (add-hook 'js2-mode-hook @@ -133,6 +165,19 @@ (set (make-local-variable 'buster-test-prefix) "") (set (make-local-variable 'js2r-use-strict) t)))) +;; jztdd + +(defun magnars/jztdd-setup () + (when (string-match-p "projects/jz-tdd" (buffer-file-name)) + (--each '("cull" "app" "JZTDD" "angular") (add-to-list 'js2-additional-externs it)) + (setq js2r-path-to-tests "/test/") + (setq js2r-path-to-sources "/public/") + (set (make-local-variable 'buster-default-global) "") + (set (make-local-variable 'buster-add-default-global-to-iife) nil) + (set (make-local-variable 'buster-test-prefix) ""))) + +(add-hook 'js2-mode-hook 'magnars/jztdd-setup) + ;; culljs (defun custom-persp/culljs () @@ -184,8 +229,6 @@ (define-key persp-mode-map (kbd "C-x p a") 'custom-persp/adventur) (project-specifics "adventur" - (set (make-local-variable 'slime-js-target-url) "http://local.adventur.no/") - (set (make-local-variable 'slime-js-connect-url) "http://local.adventur.no:8009") (ffip-local-patterns "*.js" "*.php" "*.css") (ffip-local-excludes "compiled_pages" "compiler_test_files" "simpletest" "compressed")) @@ -198,7 +241,8 @@ (defun custom-persp/adventur-master () (interactive) (custom-persp "adventur-master" - (find-file "~/projects/eventyr/master/notat.adv"))) + (require 'adventur-mode) + (find-file "~/projects/eventyr/master/notat.org"))) (define-key persp-mode-map (kbd "C-x p m") 'custom-persp/adventur-master) diff --git a/users/fimasvee/travel-mode.el b/users/fimasvee/travel-mode.el new file mode 100644 index 000000000..6f7ee9e47 --- /dev/null +++ b/users/fimasvee/travel-mode.el @@ -0,0 +1,23 @@ +(require 's) + +(defun travel-hot-deploy-buffer-file () + "If the current buffer is visiting a file, and that file is deployed +in an exploded war, re-deploy the file." + (interactive) + (let* ((source (buffer-file-name)) + (target (s-replace "src/main/webapp" "target/web" source))) + (if (and (file-writable-p target) + (not (string= source target))) + (progn + (copy-file source target t) + (message (concat "Deployed " source " to " target))) + (message (concat target " does not exist, file not deployed"))))) + +(define-minor-mode travel-mode + "Convenience utilities for working with Finn Travel" + nil " Travel" nil + (if travel-mode + (add-hook 'after-save-hook 'travel-hot-deploy-buffer-file nil t) + (remove-hook 'after-save-hook 'travel-hot-deploy-buffer-file t))) + +(provide 'travel-mode)