From c791150a0672f759acbfcbe7d86eee66cb472108 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sun, 4 Oct 2015 08:56:07 +0100 Subject: [PATCH] Add rewritten config, dubbed emacs-siren I've taken a lot of inspiration from Emacs-Prelude when it came to the structure of this rewritten config. I didn't want to use Prelude as I don't agree with all it's defaults, nor do I want to have to deal with any future changes in Prelude that might break things for me. So instead I went down the fully custom path, but heavily inspired by Prelude, both in terms of file/code structure, and also some of it's features. Compared to my old config setup, it's got most of the same things, but nearly everything is in a module file now, making it easy to fully enable/disable certain features. --- .gitignore | 1 + .gitmodules | 3 + core/siren-core.el | 45 + core/siren-custom.el | 23 + core/siren-editor.el | 207 +++ core/siren-env.el | 22 + core/siren-osx.el | 12 + core/siren-packages.el | 70 + core/siren-ui.el | 52 + custom.el | 13 + init.el | 73 + modules/siren-aliases.el | 35 + modules/siren-auto-complete.el | 32 + modules/siren-avy.el | 18 + modules/siren-coffee.el | 36 + modules/siren-company.el | 40 + modules/siren-css.el | 27 + modules/siren-cucumber.el | 22 + modules/siren-dired.el | 19 + modules/siren-ecb.el | 31 + modules/siren-elscreen.el | 27 + modules/siren-emacs-lisp.el | 47 + modules/siren-escreen.el | 69 + modules/siren-exec-path-from-shell.el | 11 + modules/siren-fci.el | 12 + modules/siren-flycheck.el | 13 + modules/siren-frame-transparency.el | 48 + modules/siren-full-ack.el | 38 + modules/siren-github.el | 10 + modules/siren-global-keybindings.el | 89 + modules/siren-go.el | 66 + modules/siren-goto-symbol.el | 56 + modules/siren-haml.el | 23 + modules/siren-helm.el | 39 + modules/siren-helpers.el | 107 ++ modules/siren-highlight-indentation.el | 12 + modules/siren-ido.el | 36 + modules/siren-linum.el | 14 + modules/siren-lisp.el | 34 + modules/siren-magit.el | 46 + modules/siren-makefile.el | 21 + modules/siren-markdown.el | 32 + modules/siren-move-beginning-of-line.el | 34 + modules/siren-multiple-cursors.el | 23 + modules/siren-neotree.el | 10 + modules/siren-perspective.el | 37 + modules/siren-phi-search.el | 12 + modules/siren-programming.el | 32 + modules/siren-project-explorer.el | 30 + modules/siren-projectile.el | 51 + modules/siren-ruby.el | 83 + modules/siren-sass.el | 19 + modules/siren-scroll-half-screen.el | 17 + modules/siren-scss.el | 19 + modules/siren-sh.el | 26 + modules/siren-smartparens.el | 26 + modules/siren-smex.el | 20 + modules/siren-text-manipulation.el | 61 + modules/siren-volatile-highlights.el | 12 + modules/siren-window-management.el | 33 + modules/siren-workgroups2.el | 11 + modules/siren-yasnippet.el | 13 + siren-modules.el | 56 + siren-theme.el | 7 + themes/siren-theme-tomorrow-night-paradise.el | 8 + themes/siren-theme-twilight-anti-bright.el | 10 + vendor/linum+.el | 158 ++ vendor/ruby-mode.el | 1584 +++++++++++++++++ vendor/tomorrow-night-paradise-theme | 1 + 69 files changed, 4024 insertions(+) create mode 100644 core/siren-core.el create mode 100644 core/siren-custom.el create mode 100644 core/siren-editor.el create mode 100644 core/siren-env.el create mode 100644 core/siren-osx.el create mode 100644 core/siren-packages.el create mode 100644 core/siren-ui.el create mode 100644 custom.el create mode 100644 modules/siren-aliases.el create mode 100644 modules/siren-auto-complete.el create mode 100644 modules/siren-avy.el create mode 100644 modules/siren-coffee.el create mode 100644 modules/siren-company.el create mode 100644 modules/siren-css.el create mode 100644 modules/siren-cucumber.el create mode 100644 modules/siren-dired.el create mode 100644 modules/siren-ecb.el create mode 100644 modules/siren-elscreen.el create mode 100644 modules/siren-emacs-lisp.el create mode 100644 modules/siren-escreen.el create mode 100644 modules/siren-exec-path-from-shell.el create mode 100644 modules/siren-fci.el create mode 100644 modules/siren-flycheck.el create mode 100644 modules/siren-frame-transparency.el create mode 100644 modules/siren-full-ack.el create mode 100644 modules/siren-github.el create mode 100644 modules/siren-global-keybindings.el create mode 100644 modules/siren-go.el create mode 100644 modules/siren-goto-symbol.el create mode 100644 modules/siren-haml.el create mode 100644 modules/siren-helm.el create mode 100644 modules/siren-helpers.el create mode 100644 modules/siren-highlight-indentation.el create mode 100644 modules/siren-ido.el create mode 100644 modules/siren-linum.el create mode 100644 modules/siren-lisp.el create mode 100644 modules/siren-magit.el create mode 100644 modules/siren-makefile.el create mode 100644 modules/siren-markdown.el create mode 100644 modules/siren-move-beginning-of-line.el create mode 100644 modules/siren-multiple-cursors.el create mode 100644 modules/siren-neotree.el create mode 100644 modules/siren-perspective.el create mode 100644 modules/siren-phi-search.el create mode 100644 modules/siren-programming.el create mode 100644 modules/siren-project-explorer.el create mode 100644 modules/siren-projectile.el create mode 100644 modules/siren-ruby.el create mode 100644 modules/siren-sass.el create mode 100644 modules/siren-scroll-half-screen.el create mode 100644 modules/siren-scss.el create mode 100644 modules/siren-sh.el create mode 100644 modules/siren-smartparens.el create mode 100644 modules/siren-smex.el create mode 100644 modules/siren-text-manipulation.el create mode 100644 modules/siren-volatile-highlights.el create mode 100644 modules/siren-window-management.el create mode 100644 modules/siren-workgroups2.el create mode 100644 modules/siren-yasnippet.el create mode 100644 siren-modules.el create mode 100644 siren-theme.el create mode 100644 themes/siren-theme-tomorrow-night-paradise.el create mode 100644 themes/siren-theme-twilight-anti-bright.el create mode 100644 vendor/linum+.el create mode 100644 vendor/ruby-mode.el create mode 160000 vendor/tomorrow-night-paradise-theme diff --git a/.gitignore b/.gitignore index 7f54bb6..e347560 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ project-explorer-cache/* recentf saved-places smex-items +savefile/* # Bittorrent Sync related .AppleDouble diff --git a/.gitmodules b/.gitmodules index e69de29..bbc713a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/tomorrow-night-paradise-theme"] + path = vendor/tomorrow-night-paradise-theme + url = https://github.com/jimeh/tomorrow-night-paradise-theme.el.git diff --git a/core/siren-core.el b/core/siren-core.el new file mode 100644 index 0000000..92f24f8 --- /dev/null +++ b/core/siren-core.el @@ -0,0 +1,45 @@ +;; +;; core stuff - again shamelessly ripped from Emacs Prelude +;; + + +(defun siren-smart-open-line-above () + "Insert an empty line above the current line. +Position the cursor at it's beginning, according to the current mode." + (interactive) + (move-beginning-of-line nil) + (newline-and-indent) + (forward-line -1) + (indent-according-to-mode)) + +(defun siren-wrap-with (s) + "Create a wrapper function for smartparens using S." + `(lambda (&optional arg) + (interactive "P") + (sp-wrap-with-pair ,s))) + +(defun siren-move-beginning-of-line (arg) + "Move point back to indentation of beginning of line. + +Move point to the first non-whitespace character on this line. +If point is already there, move to the beginning of the line. +Effectively toggle between the first non-whitespace character and +the beginning of the line. + +If ARG is not nil or 1, move forward ARG - 1 lines first. If +point reaches the beginning or end of the buffer, stop there." + (interactive "^p") + (setq arg (or arg 1)) + + ;; Move lines first + (when (/= arg 1) + (let ((line-move-visual nil)) + (forward-line (1- arg)))) + + (let ((orig-point (point))) + (back-to-indentation) + (when (= orig-point (point)) + (move-beginning-of-line 1)))) + + +(provide 'siren-core) diff --git a/core/siren-custom.el b/core/siren-custom.el new file mode 100644 index 0000000..e932f1b --- /dev/null +++ b/core/siren-custom.el @@ -0,0 +1,23 @@ +;; +;; siren custom +;; + +(defcustom siren-yank-indent-threshold 1000 + "Threshold (# chars) over which indentation does not automatically occur." + :type 'number + :group 'siren) + +(defcustom siren-indent-sensitive-modes + '(conf-mode coffee-mode haml-mode python-mode slim-mode yaml-mode) + "Modes for which auto-indenting is suppressed." + :type 'list + :group 'siren) + +(defcustom siren-yank-indent-modes '(LaTeX-mode TeX-mode) + "Modes in which to indent regions that are yanked (or yank-popped). +Only modes that don't derive from `prog-mode' should be listed here." + :type 'list + :group 'siren) + + +(provide 'siren-custom) \ No newline at end of file diff --git a/core/siren-editor.el b/core/siren-editor.el new file mode 100644 index 0000000..532d581 --- /dev/null +++ b/core/siren-editor.el @@ -0,0 +1,207 @@ +;; +;; editor +;; + +;; Set default font +(if window-system + (set-face-attribute 'default nil :family "Monaco" :height 100)) + +;; don't use tabs to indent +(setq-default indent-tabs-mode nil) + +;; but maintain correct appearance +(setq-default tab-width 8) + +;; Newline at end of file +(setq require-final-newline t) + +;; Visual Line mode - wrap lines +(visual-line-mode t) + +;; Show matching parentheses +(show-paren-mode t) + +;; Highlight current line globally +(global-hl-line-mode t) + +;; delete the selection with a keypress +(delete-selection-mode t) + +;; Electric behavior +;; (electric-layout-mode t) + +;; Cursor +(if window-system + (progn + (blink-cursor-mode t) + (setq initial-frame-alist + (cons '(cursor-type . bar) (copy-alist initial-frame-alist))) + (setq default-frame-alist + (cons '(cursor-type . bar) (copy-alist default-frame-alist)))) + (blink-cursor-mode -1)) + +;; store all backup and autosave files in the tmp dir +(setq backup-directory-alist + `((".*" . ,temporary-file-directory))) +(setq auto-save-file-name-transforms + `((".*" ,temporary-file-directory t))) + +;; autosave the undo-tree history +(setq undo-tree-history-directory-alist + `((".*" . ,temporary-file-directory))) +(setq undo-tree-auto-save-history t) + +;; smart tab behavior - indent or complete +(setq tab-always-indent 'complete) + +;; revert buffers automatically when underlying files are changed externally +(global-auto-revert-mode t) + +;; diminish keeps the modeline tidy +(require 'diminish) +(diminish 'visual-line-mode) + +;; Enable mouse support when running in a console +(unless window-system + (xterm-mouse-mode 1) + (global-set-key [mouse-4] 'scroll-down-line) + (global-set-key [mouse-5] 'scroll-up-line)) + +;; saveplace remembers your location in a file when saving files +(require 'saveplace) +(setq save-place-file (expand-file-name "saveplace" siren-savefile-dir)) +;; activate it for all buffers +(setq-default save-place t) + +;; savehist keeps track of some history +(require 'savehist) +(setq savehist-additional-variables + ;; search entries + '(search-ring regexp-search-ring) + ;; save every minute + savehist-autosave-interval 60 + ;; keep the home clean + savehist-file (expand-file-name "savehist" siren-savefile-dir)) +(savehist-mode +1) + +;; Recentf +(require 'recentf) +(recentf-mode 1) +(setq recentf-save-file (expand-file-name "recentf" siren-savefile-dir) + recentf-max-saved-items 500 + recentf-max-menu-items 100 + ;; disable recentf-cleanup on Emacs start, because it can cause + ;; problems with remote files + recentf-auto-cleanup 'never + recentf-exclude '("\\.git.*" "\\.hg.*" "\\.svn.*")) + +(defun siren-recentf-exclude-p (file) + "A predicate to decide whether to exclude FILE from recentf." + (let ((file-dir (file-truename (file-name-directory file)))) + (-any-p (lambda (dir) + (string-prefix-p dir file-dir)) + (mapcar 'file-truename (list siren-savefile-dir package-user-dir))))) + +(add-to-list 'recentf-exclude 'siren-recentf-exclude-p) + +(recentf-mode +1) + +;; meaningful names for buffers with the same name +(require 'uniquify) +(setq uniquify-buffer-name-style 'post-forward-angle-brackets + uniquify-separator "/" + uniquify-after-kill-buffer-p t ; rename after killing uniquified + uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers + +;; Display whitespace characters globally +(global-whitespace-mode t) +(diminish 'whitespace-mode) +(diminish 'global-whitespace-mode) +(setq whitespace-line-column 80) + +;; Customize Whitespace Characters +;; - Newline: \u00AC = ¬ +;; - Tab: \u2192 = → +;; \u00BB = » +;; \u25B6 = ▶ +(setq whitespace-display-mappings + (quote ((newline-mark ?\n [?\u00AC ?\n] [?$ ?\n]) + (tab-mark ?\t [?\u2192 ?\t] [?\u00BB ?\t] [?\\ ?\t])))) + +(setq whitespace-style + (quote (face tabs trailing space-before-tab newline + indentation space-after-tab tab-mark newline-mark + empty))) + +;; flyspell setup +(require 'flyspell) +(diminish 'flyspell-mode) +(setq ispell-program-name "aspell" ; use aspell instead of ispell + ispell-extra-args '("--sug-mode=ultra")) + + +;; enabled change region case commands +(put 'upcase-region 'disabled nil) +(put 'downcase-region 'disabled nil) + +;; smarter kill-ring navigation +(require 'browse-kill-ring) +(browse-kill-ring-default-keybindings) +(global-set-key (kbd "s-y") 'browse-kill-ring) + +;; automatically indenting yanked text if in programming-modes +(defun yank-advised-indent-function (beg end) + "Do indentation, as long as the region isn't too large." + (if (<= (- end beg) siren-yank-indent-threshold) + (indent-region beg end nil))) + +(defmacro advise-commands (advice-name commands class &rest body) + "Apply advice named ADVICE-NAME to multiple COMMANDS. + +The body of the advice is in BODY." + `(progn + ,@(mapcar (lambda (command) + `(defadvice ,command (,class ,(intern (concat (symbol-name command) "-" advice-name)) activate) + ,@body)) + commands))) + +(advise-commands "indent" (yank yank-pop) after + "If current mode is one of `siren-yank-indent-modes', +indent yanked text (with prefix arg don't indent)." + (if (and (not (ad-get-arg 0)) + (not (member major-mode siren-indent-sensitive-modes)) + (or (derived-mode-p 'prog-mode) + (member major-mode siren-yank-indent-modes))) + (let ((transient-mark-mode nil)) + (yank-advised-indent-function (region-beginning) (region-end))))) + +;; make a shell script executable automatically on save +(add-hook 'after-save-hook + 'executable-make-buffer-file-executable-if-script-p) + +;; .zsh file is shell script too +(add-to-list 'auto-mode-alist '("\\.zsh\\'" . shell-script-mode)) + +;; saner regex syntax +(require 're-builder) +(setq reb-re-syntax 'string) + +;; sensible undo +(global-undo-tree-mode) +(diminish 'undo-tree-mode) + +;; diff-hl +(global-diff-hl-mode +1) +(add-hook 'dired-mode-hook 'diff-hl-dired-mode) + +;; easy-kill +(global-set-key [remap kill-ring-save] 'easy-kill) +(global-set-key [remap mark-sexp] 'easy-mark) + +;; diminish various modes +;; (diminish 'hs-minor-mode) +;; (diminish 'subword-mode) + + + +(provide 'siren-editor) diff --git a/core/siren-env.el b/core/siren-env.el new file mode 100644 index 0000000..b657d7b --- /dev/null +++ b/core/siren-env.el @@ -0,0 +1,22 @@ +;; +;; env +;; + +;; Nix package manager +(push "~/.nix-profile/bin" exec-path) + +;; Homebrew +(push "/usr/local/bin" exec-path) + +;; rbenv +(setq exec-path (cons "~/.rbenv/bin" exec-path)) +(setenv "PATH" (concat "~/.rbenv/bin:" (getenv "PATH"))) +(setq exec-path (cons "~/.rbenv/shims" exec-path)) +(setenv "PATH" (concat "~/.rbenv/shims:" (getenv "PATH"))) + +;; node.js +(setq exec-path (cons "~/.nvm/versions/node/v0.12.4/bin" exec-path)) +(setenv "PATH" (concat "~/.nvm/versions/node/v0.12.4/bin:" (getenv "PATH"))) + + +(provide 'siren-env) diff --git a/core/siren-osx.el b/core/siren-osx.el new file mode 100644 index 0000000..3b15972 --- /dev/null +++ b/core/siren-osx.el @@ -0,0 +1,12 @@ +;; +;; osx +;; + +;; It's all in the Meta +(setq ns-function-modifier 'hyper) + +;; Don't use OSX Native fullscreen mode +(setq ns-use-native-fullscreen nil) + + +(provide 'siren-osx) \ No newline at end of file diff --git a/core/siren-packages.el b/core/siren-packages.el new file mode 100644 index 0000000..3b5d899 --- /dev/null +++ b/core/siren-packages.el @@ -0,0 +1,70 @@ +;; +;; packages +;; + +(require 'cl) +(require 'package) + +(add-to-list 'package-archives + '("melpa" . "http://melpa.org/packages/") t) + +;; set package-user-dir to be relative to config path +(setq package-user-dir (expand-file-name "elpa" siren-dir)) +(package-initialize) + +(defvar siren-packages + '(browse-kill-ring + dash + discover-my-major + diff-hl + diminish + easy-kill + epl + gist + git-timemachine + gitconfig-mode + gitignore-mode + ; god-mode + grizzl + ; operate-on-number + smart-mode-line + ; smartrep + undo-tree + ) + "A list of default packages to ensure are installed at launch.") + +;; +;; Package helpers (borrowed from Emacs Prelude) +;; + +(defun siren-packages-installed-p () + "Check if all packages in `siren-packages' are installed." + (every #'package-installed-p siren-packages)) + +(defun siren-require-package (package) + "Install PACKAGE unless already installed." + (unless (memq package siren-packages) + (add-to-list 'siren-packages package)) + (unless (package-installed-p package) + (package-install package))) + +(defun siren-require-packages (packages) + "Ensure PACKAGES are installed. +Missing packages are installed automatically." + (mapc #'siren-require-package packages)) + +(defun siren-install-packages () + "Install all packages listed in `siren-packages'." + (unless (siren-packages-installed-p) + ;; check for new packages (package versions) + (message "%s" "Emacs is now refreshing its package database...") + (package-refresh-contents) + (message "%s" " done.") + ;; install the missing packages + (siren-require-packages siren-packages))) + +;; Install Melpa packages +(siren-install-packages) + + +(provide 'siren-packages) diff --git a/core/siren-ui.el b/core/siren-ui.el new file mode 100644 index 0000000..6c63842 --- /dev/null +++ b/core/siren-ui.el @@ -0,0 +1,52 @@ +;; +;; ui +;; + +;; the toolbar is just a waste of valuable screen estate +;; in a tty tool-bar-mode does not properly auto-load, and is +;; already disabled anyway +(when (fboundp 'tool-bar-mode) + (tool-bar-mode -1)) + +(menu-bar-mode -1) + +;; disable startup screen +(setq inhibit-startup-screen t) + +;; Disable Scrollbar +(if window-system (set-scroll-bar-mode 'nil)) + +;; nice scrolling +;; (setq scroll-margin 0 +;; scroll-conservatively 100000 +;; scroll-preserve-screen-position 1) +;; (setq redisplay-dont-pause t) +(setq mouse-wheel-scroll-amount '(1 ((shift) . 10))) ;; one line at a time +(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse +(setq scroll-margin 4) +(setq scroll-step 1) +(setq scroll-conservatively 10000) + +;; mode line settings +(line-number-mode t) +(column-number-mode t) +(size-indication-mode t) + +;; enable y/n answers +(fset 'yes-or-no-p 'y-or-n-p) + +;; more useful frame title, that show either a file or a +;; buffer name (if the buffer isn't visiting a file) +(setq frame-title-format + '("Emacs - " (:eval (if (buffer-file-name) + (abbreviate-file-name (buffer-file-name)) + "%b")))) + +(require 'smart-mode-line) +(setq sml/no-confirm-load-theme t) +;; delegate theming to the currently active theme +(setq sml/theme nil) +(add-hook 'after-init-hook #'sml/setup) + + +(provide 'siren-ui) diff --git a/custom.el b/custom.el new file mode 100644 index 0000000..ed6b9c0 --- /dev/null +++ b/custom.el @@ -0,0 +1,13 @@ +(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. + '(ecb-options-version "2.40") + '(magit-commit-arguments (quote ("-S")))) +(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. + '(sp-pair-overlay-face ((t (:inherit nil))))) diff --git a/init.el b/init.el index 5162ee0..05cf620 100644 --- a/init.el +++ b/init.el @@ -9,3 +9,76 @@ ;; the `packages.el' file that's loaded in further down. ;; ;; (package-initialize) + +(defvar current-user + (getenv + (if (equal system-type 'windows-nt) "USERNAME" "USER"))) + +(message "Siren is powering up... Be patient, Master %s!" current-user) + +(when (version< emacs-version "24.1") + (error "Siren requires at least GNU Emacs 24.1, but you're running %s" emacs-version)) + +;; Always load newest byte code +(setq load-prefer-newer t) + +;; Setup paths +(defvar siren-dir (file-name-directory load-file-name) + "The root dir of the Emacs config.") +(defvar siren-core-dir (expand-file-name "core" siren-dir) + "The home of core stuff.") +(defvar siren-modules-dir (expand-file-name "modules" siren-dir) + "This directory houses all of the modules.") +(defvar siren-themes-dir (expand-file-name "themes" siren-dir) + "This directory houses all of the modules.") +(defvar siren-savefile-dir (expand-file-name "savefile" siren-dir) + "This folder stores all the automatically generated save/history-files.") +(defvar siren-vendor-dir (expand-file-name "vendor" siren-dir) + "This directory houses packages that are not yet available in ELPA (or MELPA).") + +(defvar siren-modules-file (expand-file-name "siren-modules.el" siren-dir) + "This files contains a list of modules to be loaded.") +(defvar siren-theme-file (expand-file-name "siren-theme.el" siren-dir) + "This files contains a list of modules to be loaded.") + +(unless (file-exists-p siren-savefile-dir) + (make-directory siren-savefile-dir)) + +(defun siren-add-subfolders-to-load-path (parent-dir) + "Add all level PARENT-DIR subdirs to the `load-path'." + (dolist (f (directory-files parent-dir)) + (let ((name (expand-file-name f parent-dir))) + (when (and (file-directory-p name) + (not (string-prefix-p "." f))) + (add-to-list 'load-path name) + (siren-add-subfolders-to-load-path name))))) + +(add-to-list 'load-path siren-core-dir) +(add-to-list 'load-path siren-modules-dir) +(add-to-list 'load-path siren-themes-dir) +(add-to-list 'load-path siren-vendor-dir) +(siren-add-subfolders-to-load-path siren-vendor-dir) + +;; core stuff +(require 'siren-env) +(require 'siren-custom) +(require 'siren-core) +(require 'siren-packages) +(require 'siren-ui) +(require 'siren-editor) + +;; osx specific +(when (eq system-type 'darwin) + (require 'siren-osx)) + +;; config changes made through the customize UI will be store here +(setq custom-file (expand-file-name "custom.el" siren-dir)) +(load-file custom-file) + +;; the modules +(if (file-exists-p siren-modules-file) + (load siren-modules-file)) + +;; the theme +(if (file-exists-p siren-theme-file) + (load siren-theme-file)) diff --git a/modules/siren-aliases.el b/modules/siren-aliases.el new file mode 100644 index 0000000..a431834 --- /dev/null +++ b/modules/siren-aliases.el @@ -0,0 +1,35 @@ +;; +;; Setup a few global command aliases +;; + +;; Text Manipulation +(defalias 'rs 'replace-string) +(defalias 'qr 'query-replace-regexp) +(defalias 'al 'align-regexp) +(defalias 'sl 'sort-lines) +(defalias 'rr 'reverse-region) +(defalias 'wc 'whitespace-cleanup) + +(defalias 'lml 'list-matching-lines) +(defalias 'dml 'delete-matching-lines) +(defalias 'dnml 'delete-non-matching-lines) +(defalias 'dtw 'delete-trailing-whitespace) + +;; Buffer Manipulation +(defalias 'rb 'revert-buffer) + +;; Emacs Lisp +(defalias 'eb 'eval-buffer) +(defalias 'er 'eval-region) +(defalias 'ed 'eval-defun) +(defalias 'eis 'elisp-index-search) +(defalias 'lf 'load-file) + +;; Dired +(defalias 'wd 'wdired-change-to-wdired-mode) + +;; Modes +(defalias 'sh 'shell-script-mode) + + +(provide 'siren-aliases) \ No newline at end of file diff --git a/modules/siren-auto-complete.el b/modules/siren-auto-complete.el new file mode 100644 index 0000000..47a9cbd --- /dev/null +++ b/modules/siren-auto-complete.el @@ -0,0 +1,32 @@ +;; +;; auto-complete +;; + +(siren-require-packages '(auto-complete)) + +(require 'auto-complete) +;; (require 'auto-complete-config) +;; (ac-config-default) +(ac-flyspell-workaround) + +(setq ac-auto-show-menu 0.2) +(setq ac-auto-start 3) +(setq ac-delay 0.05) +(setq ac-menu-height 15) + +(let ((map ac-completing-map)) + (define-key map (kbd "RET") 'ac-complete) + (define-key map (kbd "C-m") 'ac-complete) + (define-key map (kbd "C-s") 'ac-isearch) + (define-key map (kbd "C-n") 'ac-next) + (define-key map (kbd "C-p") 'ac-previous)) + +;; Auto-complete when indenting. +(defadvice indent-for-tab-command (around ac-before-indent activate) + "Call `auto-complete' if text was recently entered" + (if (ac-trigger-command-p last-command) + (auto-complete) + ad-do-it)) + + +(provide 'siren-auto-complete) diff --git a/modules/siren-avy.el b/modules/siren-avy.el new file mode 100644 index 0000000..72cc29d --- /dev/null +++ b/modules/siren-avy.el @@ -0,0 +1,18 @@ +;; +;; avy allows us to effectively navigate to visible things +;; + +(siren-require-packages '(ace-window avy)) + +(require 'avy) +(require 'ace-window) + +(setq avy-background t + avy-style 'at-full) + +(define-key global-map (kbd "C-c C-j") 'avy-goto-word-or-subword-1) +(define-key global-map (kbd "C-c SPC") 'avy-goto-char) +(define-key global-map (kbd "M-o") 'ace-window) + + +(provide 'siren-avy) \ No newline at end of file diff --git a/modules/siren-coffee.el b/modules/siren-coffee.el new file mode 100644 index 0000000..4412147 --- /dev/null +++ b/modules/siren-coffee.el @@ -0,0 +1,36 @@ +;; +;; coffeescript +;; + +(require 'siren-programming) + +(eval-after-load 'coffee-mode + '(progn + (siren-require-packages '(coffee-mode)) + + (setq coffee-tab-width 2) + + ;; remove the "Generated by CoffeeScript" header + (add-to-list 'coffee-args-compile "--no-header") + + (defun siren-coffee-mode-defaults () + (siren-prog-mode-defaults) + + ;; Update the already compiled js on save + (and (buffer-file-name) + (file-exists-p (buffer-file-name)) + (file-exists-p (coffee-compiled-file-name (buffer-file-name))) + (coffee-cos-mode t)) + + (setq tab-width 2) + (highlight-indentation-mode) + (highlight-indentation-current-column-mode) + (subword-mode +1)) + + (setq siren-coffee-mode-hook 'siren-coffee-mode-defaults) + + (add-hook 'coffee-mode-hook (lambda () + (run-hooks 'siren-coffee-mode-hook))))) + + +(provide 'siren-coffee) diff --git a/modules/siren-company.el b/modules/siren-company.el new file mode 100644 index 0000000..39a2286 --- /dev/null +++ b/modules/siren-company.el @@ -0,0 +1,40 @@ +;; +;; company +;; + +(siren-require-packages '(company)) + +(require 'company) + +(setq company-idle-delay 0.5 + company-tooltip-limit 10 + company-minimum-prefix-length 2) + +;; invert the navigation direction if the the completion popup-isearch-match +;; is displayed on top (happens near the bottom of windows) +(setq company-tooltip-flip-when-above t) + +(global-company-mode 1) + + +;; Trigger completion popup by pressing tab +;; - from: https://github.com/company-mode/company-mode/issues/94#issuecomment-40884387 +(define-key company-mode-map [remap indent-for-tab-command] + 'company-indent-for-tab-command) + +(setq tab-always-indent 'complete) + +(defvar completion-at-point-functions-saved nil) + +(defun company-indent-for-tab-command (&optional arg) + (interactive "P") + (let ((completion-at-point-functions-saved completion-at-point-functions) + (completion-at-point-functions '(company-complete-common-wrapper))) + (indent-for-tab-command arg))) + +(defun company-complete-common-wrapper () + (let ((completion-at-point-functions completion-at-point-functions-saved)) + (company-complete-common))) + + +(provide 'siren-company) diff --git a/modules/siren-css.el b/modules/siren-css.el new file mode 100644 index 0000000..be51d7f --- /dev/null +++ b/modules/siren-css.el @@ -0,0 +1,27 @@ +;; +;; css +;; + +(require 'siren-programming) + +(eval-after-load 'css-mode + '(progn + (siren-require-packages '(rainbow-mode)) + + (setq css-indent-offset 2) + + (defun siren-css-mode-defaults () + (siren-prog-mode-defaults) + (rainbow-mode +1) + (setq tab-width 2) + (highlight-indentation-mode) + (highlight-indentation-current-column-mode) + (run-hooks 'siren-prog-mode-hook)) + + (setq siren-css-mode-hook 'siren-css-mode-defaults) + + (add-hook 'css-mode-hook (lambda () + (run-hooks 'siren-css-mode-hook))))) + + +(provide 'siren-css) diff --git a/modules/siren-cucumber.el b/modules/siren-cucumber.el new file mode 100644 index 0000000..136dde2 --- /dev/null +++ b/modules/siren-cucumber.el @@ -0,0 +1,22 @@ +;; +;; feature +;; + +(require 'siren-programming) + +(siren-require-packages '(feature-mode)) + +(defun siren-feature-mode-defaults () + (siren-prog-mode-defaults) + (setq tab-width 2) + (setq highlight-indentation-offset 2) + (highlight-indentation-mode) + (highlight-indentation-current-column-mode)) + +(setq siren-feature-mode-hook 'siren-feature-mode-defaults) + +(add-hook 'feature-mode-hook (lambda () + (run-hooks 'siren-feature-mode-hook))) + + +(provide 'siren-cucumber) diff --git a/modules/siren-dired.el b/modules/siren-dired.el new file mode 100644 index 0000000..f4685e4 --- /dev/null +++ b/modules/siren-dired.el @@ -0,0 +1,19 @@ +;; +;; dired +;; + +(siren-require-packages '(dired+)) +(require 'dired+) + +(defun siren-dired-mode-defaults () + (linum-mode t) + (define-key dired-mode-map (kbd "c") 'dired-create-directory) + (toggle-diredp-find-file-reuse-dir 1)) + +(setq siren-dired-mode-hook 'siren-dired-mode-defaults) + +(add-hook 'dired-mode-hook (lambda () + (run-hooks 'siren-dired-mode-hook))) + + +(provide 'siren-dired) diff --git a/modules/siren-ecb.el b/modules/siren-ecb.el new file mode 100644 index 0000000..5d10915 --- /dev/null +++ b/modules/siren-ecb.el @@ -0,0 +1,31 @@ +;; +;; ecb +;; + +(siren-require-packages '(ecb)) + +(require 'ecb) + +(setq ecb-layout-name "left13") +(setq ecb-primary-secondary-mouse-buttons (quote mouse-1--mouse-2)) +(setq ecb-tree-make-parent-node-sticky nil) +(setq ecb-prescan-directories-for-emptyness nil) +(setq ecb-tip-of-the-day nil) +(setq ecb-tree-indent 3) +(setq ecb-windows-width 0.24) +(setq ecb-source-path + (quote + (("~/Projects" "Projects") + ("~/.emacs.d" ".emacs.d") + ("~/.dotfiles" ".dotfiles") + ("~/Projects/fitzdares" "fitzdares") + ("~/.go" ".go") + ("~/src" "src") + ("~/Sites" "Sites") + ("~" "~") + ("/" "/")))) + +(if window-system (ecb-activate)) + + +(provide 'siren-ecb) diff --git a/modules/siren-elscreen.el b/modules/siren-elscreen.el new file mode 100644 index 0000000..d8a23fe --- /dev/null +++ b/modules/siren-elscreen.el @@ -0,0 +1,27 @@ +;; +;; elscreen +;; + +(siren-require-packages '(elscreen)) + +(require 'elscreen) +(define-key elscreen-map (kbd "C-z") elscreen-map) + +;; Goto screens. +(global-set-key (kbd "s-}") 'elscreen-next) +(global-set-key (kbd "s-{") 'elscreen-previous) + +;; Set screen nickname +(define-key elscreen-map (kbd ",") 'elscreen-screen-nickname) +(define-key elscreen-map (kbd "C-,") 'elscreen-screen-nickname) + +;; Toggle screens. +(define-key elscreen-map (kbd "l") 'elscreen-toggle) +(define-key elscreen-map (kbd "C-l") 'elscreen-toggle) + +;; Display list of screens. +(define-key elscreen-map (kbd ";") 'elscreen-display-screen-name-list) +(define-key elscreen-map (kbd "C-;") 'elscreen-display-screen-name-list) + + +(provide 'siren-elscreen) \ No newline at end of file diff --git a/modules/siren-emacs-lisp.el b/modules/siren-emacs-lisp.el new file mode 100644 index 0000000..3641a37 --- /dev/null +++ b/modules/siren-emacs-lisp.el @@ -0,0 +1,47 @@ +;; +;; emacs-lisp +;; + +(siren-require-packages '(rainbow-mode)) + +(require 'siren-lisp) + +(defun siren-recompile-elc-on-save () + "Recompile your elc when saving an elisp file." + (add-hook 'after-save-hook + (lambda () + (when (and + (string-prefix-p siren-dir (file-truename buffer-file-name)) + (file-exists-p (byte-compile-dest-file buffer-file-name))) + (emacs-lisp-byte-compile))) + nil + t)) + +(defun siren-conditional-emacs-lisp-checker () + "Don't check doc style in Emacs Lisp test files." + (let ((file-name (buffer-file-name))) + (when (and file-name (string-match-p ".*-tests?\\.el\\'" file-name)) + (setq-local flycheck-checkers '(emacs-lisp))))) + +(defun siren-emacs-lisp-mode-defaults () + "Sensible defaults for `emacs-lisp-mode'." + ; (run-hooks 'siren-lisp-coding-hook) + ; (eldoc-mode +1) + ; (siren-recompile-elc-on-save) + ; (rainbow-mode +1) + ; (setq mode-name "EL") + ; (siren-conditional-emacs-lisp-checker) + ) + +(setq siren-emacs-lisp-mode-hook 'siren-emacs-lisp-mode-defaults) + +(add-hook 'emacs-lisp-mode-hook (lambda () + (run-hooks 'siren-emacs-lisp-mode-hook))) + +(add-to-list 'auto-mode-alist '("Cask\\'" . emacs-lisp-mode)) + +(eval-after-load "rainbow-mode" + '(diminish 'rainbow-mode)) + + +(provide 'siren-emacs-lisp) diff --git a/modules/siren-escreen.el b/modules/siren-escreen.el new file mode 100644 index 0000000..ef41d87 --- /dev/null +++ b/modules/siren-escreen.el @@ -0,0 +1,69 @@ +;; +;; escreen +;; + +(siren-require-packages '(escreen)) + +(require 'escreen) + +;; +;; Escreen Helper +;; - from http://blog.nguyenvq.com/2011/03/07/escreen-instead-of-elscreen-for-screen-like-features-in-emacs/ +;; + +(defun escreen-get-active-screen-numbers-with-emphasis () + "what the name says" + (interactive) + (let ((escreens (escreen-get-active-screen-numbers)) + (emphased "")) + (dolist (s escreens) + (setq emphased + (concat emphased (if (= escreen-current-screen-number s) + (propertize (number-to-string s) + ;;'face 'custom-variable-tag) " ") + ;;'face 'info-title-3) + 'face 'font-lock-warning-face) + ;;'face 'secondary-selection) + (number-to-string s)) + " "))) + (message "escreen: active screens: %s" emphased))) + +;; Initialize escreen +(escreen-install) + +;; Set prefix key to C-z. +(setq escreen-prefix-char (kbd "C-z")) +(global-set-key escreen-prefix-char 'escreen-prefix) +(define-key escreen-map escreen-prefix-char 'escreen-goto-last-screen) + +;; Toggle screens. +(define-key escreen-map (kbd "l") 'escreen-goto-last-screen) +(define-key escreen-map (kbd "C-l") 'escreen-goto-last-screen) + +;; List screens. +(define-key escreen-map (kbd "a") + 'escreen-get-active-screen-numbers-with-emphasis) +(define-key escreen-map (kbd "C-a") + 'escreen-get-active-screen-numbers-with-emphasis) +(define-key escreen-map (kbd ";") + 'escreen-get-active-screen-numbers-with-emphasis) +(define-key escreen-map (kbd "C-;") + 'escreen-get-active-screen-numbers-with-emphasis) + +;; Goto screens. +(global-set-key (kbd "s-}") 'escreen-goto-next-screen) +(global-set-key (kbd "s-{") 'escreen-goto-prev-screen) + +;; Ctrl versions of default commands. +(define-key escreen-map (kbd "C-c") 'escreen-create-screen) +(define-key escreen-map (kbd "C-g") 'escreen-goto-screen) +(define-key escreen-map (kbd "C-k") 'escreen-kill-screen) +(define-key escreen-map (kbd "C-n") 'escreen-goto-next-screen) +(define-key escreen-map (kbd "C-p") 'escreen-goto-prev-screen) + +;; Show list of screens when you switch/create/kill. +(add-hook 'escreen-goto-screen-hook + 'escreen-get-active-screen-numbers-with-emphasis) + + +(provide 'siren-escreen) \ No newline at end of file diff --git a/modules/siren-exec-path-from-shell.el b/modules/siren-exec-path-from-shell.el new file mode 100644 index 0000000..c19de89 --- /dev/null +++ b/modules/siren-exec-path-from-shell.el @@ -0,0 +1,11 @@ +;; +;; exec-path-from-shell +;; + +(siren-require-packages '(exec-path-from-shell)) + +(require 'exec-path-from-shell) +(when (memq window-system '(mac ns)) + (exec-path-from-shell-initialize)) + +(provide 'siren-exec-path-from-shell) diff --git a/modules/siren-fci.el b/modules/siren-fci.el new file mode 100644 index 0000000..1f1bf34 --- /dev/null +++ b/modules/siren-fci.el @@ -0,0 +1,12 @@ +;; +;; fci +;; + +(siren-require-packages '(fill-column-indicator)) + +(require 'fill-column-indicator) +(setq fci-rule-width 1 + fci-handle-trucate-lines nil) + + +(provide 'siren-fci) \ No newline at end of file diff --git a/modules/siren-flycheck.el b/modules/siren-flycheck.el new file mode 100644 index 0000000..40a5870 --- /dev/null +++ b/modules/siren-flycheck.el @@ -0,0 +1,13 @@ +;; +;; flycheck +;; + +(siren-require-packages '(flycheck)) + +(require 'flycheck) +(setq flycheck-completion-system 'ido) +(setq flycheck-idle-change-delay 1.0) +(setq flycheck-indication-mode 'right-fringe) + + +(provide 'siren-flycheck) diff --git a/modules/siren-frame-transparency.el b/modules/siren-frame-transparency.el new file mode 100644 index 0000000..be21b96 --- /dev/null +++ b/modules/siren-frame-transparency.el @@ -0,0 +1,48 @@ +;; +;; frame transparency +;; + +(defun siren-frame-transparency-fix () + "Set initial value of alpha parameter for the current frame" + (interactive) + (if (equal (frame-parameter nil 'alpha) nil) + (set-frame-parameter nil 'alpha 100))) + +(defun siren-frame-transparency-increase () + "Increase level of transparency for the current frame" + (interactive) + (siren-frame-transparency-fix) + (if (> (frame-parameter nil 'alpha) 0) + (set-frame-parameter nil 'alpha (+ (frame-parameter nil 'alpha) -1)) + (message "This is a minimum value of transparency!"))) + +(defun siren-frame-transparency-decrease () + "Decrease level of transparency for the current frame" + (interactive) + (siren-frame-transparency-fix) + (if (< (frame-parameter nil 'alpha) 100) + (set-frame-parameter nil 'alpha (+ (frame-parameter nil 'alpha) +1)) + (message "This is a minimum value of transparency!"))) + +(defun siren-frame-transparency (numb) + "Set level of transparency for the current frame" + (interactive "nEnter transparency level in range 0-100: ") + (if (> numb 100) + (message "Error! The maximum value for transparency is 100!") + (if (< numb 0) + (message "Error! The minimum value for transparency is 0!") + (set-frame-parameter nil 'alpha numb)))) + +(setq siren-transparency-level 99) +(siren-frame-transparency siren-transparency-level) +(add-hook 'after-make-frame-functions + (lambda (selected-frame) + (set-frame-parameter selected-frame 'alpha siren-transparency-level))) + +;; Keybindings +(global-set-key (kbd "C-M-|") 'siren-frame-transparency) +(global-set-key (kbd "C-M-<") 'siren-frame-transparency-increase) +(global-set-key (kbd "C-M->") 'siren-frame-transparency-decrease) + + +(provide 'siren-frame-transparency) diff --git a/modules/siren-full-ack.el b/modules/siren-full-ack.el new file mode 100644 index 0000000..01746ee --- /dev/null +++ b/modules/siren-full-ack.el @@ -0,0 +1,38 @@ +;; +;; full-ack +;; + +(siren-require-packages '(full-ack)) + +(require 'full-ack) +(setq ack-arguments + (quote ("--ignore-dir=vendor/ruby" + "--ignore-dir=vendor/bundle" + "--ignore-dir=coverage" + "--ignore-dir=savefile" + "--ignore-dir=Godeps" + "--ignore-dir=elpa" + "--ignore-dir=docs" + "--ignore-dir=doc" + "--type-add=js=.js,.js.erb" + "--type-add=ruby=.jbuilder,.rabl" + "--type-add=html=.haml,.hamlc,.jade" + "--type-add=css=.sass,.scss,.styl" + "--type-set=coffee=.coffee" + "--type-set=cucumber=.feature"))) +(setq ack-project-root-file-patterns + (quote (".project\\'" + ".xcodeproj\\'" + ".sln\\'" + "\\`Project.ede\\'" + "\\`.git\\'" + "\\`.bzr\\'" + "\\`_darcs\\'" + "\\`.hg\\'" + "\\`Gemfile\\'" + "\\`Rakefile\\'" + "\\`Makefile\\'"))) +(setq ack-prompt-for-directory 'unless-guessed) + + +(provide 'siren-full-ack) diff --git a/modules/siren-github.el b/modules/siren-github.el new file mode 100644 index 0000000..3da631d --- /dev/null +++ b/modules/siren-github.el @@ -0,0 +1,10 @@ +;; +;; github +;; + +(siren-require-packages '(github-browse-file)) + +(require 'github-browse-file) + + +(provide 'siren-github) diff --git a/modules/siren-global-keybindings.el b/modules/siren-global-keybindings.el new file mode 100644 index 0000000..05be4da --- /dev/null +++ b/modules/siren-global-keybindings.el @@ -0,0 +1,89 @@ +;; +;; global keybindings (customized) +;; + +(require 'siren-helpers) + +;; Enable dabbrev-expand via custom keybinding. +(global-set-key (kbd "C-x M-/") 'dabbrev-expand) + +;; Easier version of "C-x k" to kill buffer +(global-set-key (kbd "C-x C-k") 'kill-buffer) + +;; Evaluate buffer +(global-set-key (kbd "C-c C-e") 'eval-buffer) + +;; Duplicate line (via siren-helpers.el) +(global-set-key (kbd "C-x C-d") 'duplicate-current-line-or-region) + +;; Switch to next/previous buffer +(global-set-key (kbd "C-c C-n") 'switch-to-next-buffer) +(global-set-key (kbd "C-c C-p") 'switch-to-prev-buffer) + +;; Window switching (via siren-helpers.el). +(global-set-key (kbd "C-x i") 'other-window-reverse) +(global-set-key (kbd "C-x C-o") 'other-window) +(global-set-key (kbd "C-x C-i") 'other-window-reverse) + +;; Kill-Ring related (via siren-helpers.el). +(global-set-key (kbd "M-Y") 'yank-pop-forwards) + +;; Align to equal signs (via siren-helpers.el). +(global-set-key (kbd "C-x a =") 'align-region-to-equals) +(global-set-key (kbd "M-]") 'align-region-to-equals) +(global-set-key (kbd "C-x a {") 'align-region-to-opening-brace) + +;; align-regexp +(global-set-key (kbd "C-c C-a") 'align-regexp) + +;; Toggle auto-fill-mode. +(global-set-key (kbd "C-c q") 'auto-fill-mode) + +;; Custom HideShow toggles (via siren-helpers.el) +(global-set-key (kbd "C-=") 'toggle-selective-display) +(global-set-key (kbd "C-\\") 'toggle-hiding) + +;; undo/redo via undo-tree +(global-set-key (kbd "M--") 'undo-tree-undo) +(global-set-key (kbd "M-_") 'undo-tree-redo) + +;; iBuffer +(global-set-key (kbd "C-x C-b") 'ibuffer) + +;; String inflections +(siren-require-packages '(string-inflection)) +(require 'string-inflection) +(global-set-key (kbd "C-c C-.") 'string-inflection-cycle) + +;; Rename current file and buffer (via siren-helpers.el) +(global-set-key (kbd "C-c r") 'rename-file-and-buffer) + +;; Use siren-move-beginning-of-line +(global-set-key (kbd "C-a") 'siren-move-beginning-of-line) + +;; Mac OS X specific keybindings +(when (eq system-type 'darwin) + + ;; Mac OS X Fullscreen (requires Emacs 24.4 or later) + (global-set-key (kbd "s-") 'toggle-frame-fullscreen) + + ;; Undo/Redo (via undo-tree) + (when (require 'undo-tree nil 'noerror) + (global-set-key (kbd "s-z") 'undo-tree-undo) + (global-set-key (kbd "s-Z") 'undo-tree-redo)) + + ;; Flyspell correct previous word + (when (require 'flyspell nil 'noerror) + (global-set-key (kbd "s-.") 'flyspell-correct-word-before-point)) + + ;; Move to beginning/end of buffer + (global-set-key (kbd "s-") 'beginning-of-buffer) + (global-set-key (kbd "s-") 'end-of-buffer) + + ;; Move to beginning/end of line + (global-set-key (kbd "s-") 'beginning-of-line) + (global-set-key (kbd "s-") 'end-of-line)) + + + +(provide 'siren-global-keybindings) diff --git a/modules/siren-go.el b/modules/siren-go.el new file mode 100644 index 0000000..18eced1 --- /dev/null +++ b/modules/siren-go.el @@ -0,0 +1,66 @@ +;; +;; go +;; + +(require 'siren-programming) + +(setenv "GOPATH" (expand-file-name "~/.go")) + +;; Ignore go test -c output files +(add-to-list 'completion-ignored-extensions ".test") + +(define-key 'help-command (kbd "G") 'godoc) + +(eval-after-load 'go-mode + '(progn + (siren-require-packages + '(go-mode go-autocomplete go-eldoc go-projectile gotest)) + + (require 'go-projectile) + (require 'go-autocomplete) + + (defun siren-go-mode-defaults () + (siren-prog-mode-defaults) + + ;; Add to default go-mode key bindings + (let ((map go-mode-map)) + (define-key map (kbd "RET") 'newline-and-indent) + (define-key map (kbd "C-c a") 'go-test-current-project) + (define-key map (kbd "C-c m") 'go-test-current-file) + (define-key map (kbd "C-c .") 'go-test-current-test) + (define-key map (kbd "C-c b") 'go-run) + (define-key map (kbd "C-h f") 'godoc-at-point)) + + ;; Prefer goimports to gofmt if installed + (let ((goimports (executable-find "goimports"))) + (when goimports + (setq gofmt-command goimports))) + + ;; gofmt on save + (add-hook 'before-save-hook 'gofmt-before-save nil t) + + ;; enable hide/show + (hs-minor-mode 1) + + ;; stop whitespace being highlighted + (whitespace-toggle-options '(tabs)) + + ;; enable auto-complete + (auto-complete-mode +1) + + ;; make tabs 4 spaces wide + (setq tab-width 4) + + ;; El-doc for Go + ;; (go-eldoc-setup) + + ;; CamelCase aware editing operations + (subword-mode +1)) + + (setq siren-go-mode-hook 'siren-go-mode-defaults) + + (add-hook 'go-mode-hook (lambda () + (run-hooks 'siren-go-mode-hook))))) + + +(provide 'siren-go) diff --git a/modules/siren-goto-symbol.el b/modules/siren-goto-symbol.el new file mode 100644 index 0000000..62758b5 --- /dev/null +++ b/modules/siren-goto-symbol.el @@ -0,0 +1,56 @@ +;; +;; goto-symbol +;; + +;; Shamelessly ripped from Emacs Prelude. + +(require 'imenu) +(set-default 'imenu-auto-rescan t) +(set-default 'imenu-max-item-length 160) +(set-default 'imenu-max-items 100) + +(defun siren-goto-symbol (&optional symbol-list) + "Refresh imenu and jump to a place in the buffer using Ido." + (interactive) + (cond + ((not symbol-list) + (let (name-and-pos symbol-names position) + (while (progn + (imenu--cleanup) + (setq imenu--index-alist nil) + (siren-goto-symbol (imenu--make-index-alist)) + (setq selected-symbol + (completing-read "Symbol? " (reverse symbol-names))) + (string= (car imenu--rescan-item) selected-symbol))) + (unless (and (boundp 'mark-active) mark-active) + (push-mark nil t nil)) + (setq position (cdr (assoc selected-symbol name-and-pos))) + (cond + ((overlayp position) + (goto-char (overlay-start position))) + (t + (goto-char position))) + (recenter))) + ((listp symbol-list) + (dolist (symbol symbol-list) + (let (name position) + (cond + ((and (listp symbol) (imenu--subalist-p symbol)) + (siren-goto-symbol symbol)) + ((listp symbol) + (setq name (car symbol)) + (setq position (cdr symbol))) + ((stringp symbol) + (setq name symbol) + (setq position + (get-text-property 1 'org-imenu-marker symbol)))) + (unless (or (null position) (null name) + (string= (car imenu--rescan-item) name)) + (add-to-list 'symbol-names (substring-no-properties name)) + (add-to-list 'name-and-pos (cons (substring-no-properties name) position)))))))) + + +(global-set-key (kbd "C-t") 'siren-goto-symbol) + + +(provide 'siren-goto-symbol) diff --git a/modules/siren-haml.el b/modules/siren-haml.el new file mode 100644 index 0000000..b19f8d8 --- /dev/null +++ b/modules/siren-haml.el @@ -0,0 +1,23 @@ +;; +;; haml +;; + +(siren-require-packages '(haml-mode)) + +(require 'siren-programming) + +(add-to-list 'auto-mode-alist '("\\.hamlc\\'" . haml-mode)) + +(defun siren-haml-mode-defaults () + (siren-prog-mode-defaults) + (setq tab-width 2) + (setq highlight-indentation-offset 2) + (highlight-indentation-mode) + (highlight-indentation-current-column-mode)) + +(setq siren-haml-mode-hook 'siren-haml-mode-defaults) + +(add-hook 'haml-mode-hook (lambda () (run-hooks 'siren-haml-mode-hook))) + + +(provide 'siren-haml) diff --git a/modules/siren-helm.el b/modules/siren-helm.el new file mode 100644 index 0000000..2e08c76 --- /dev/null +++ b/modules/siren-helm.el @@ -0,0 +1,39 @@ +;; +;; helm +;; + +(siren-require-packages '(helm helm-swoop helm-projectile helm-open-github)) + +(require 'helm) +(require 'helm-swoop) +(require 'helm-projectile) +(require 'helm-open-github) + +(setq helm-ag-source-type "file-line" + helm-open-github-commit-limit 10000) + +;; Helm +(define-key helm-map (kbd "") 'previous-history-element) +(define-key helm-map (kbd "") 'next-history-element) +(define-key helm-map (kbd "M-p") 'helm-previous-source) +(define-key helm-map (kbd "M-n") 'helm-next-source) +(global-set-key (kbd "C-c h") 'helm-mini) + +;; Helm Swoop +(global-set-key (kbd "M-r") 'helm-swoop) +(global-set-key (kbd "M-R") 'helm-swoop-back-to-last-point) +(global-set-key (kbd "C-c M-r") 'helm-multi-swoop) +(global-set-key (kbd "C-x M-r") 'helm-multi-swoop-all) + +;; Helm Projectile +(global-set-key (kbd "C-c ;") 'helm-projectile) +(global-set-key (kbd "C-c C-;") 'helm-projectile) + +;; Helm Open Github +(global-set-key (kbd "C-c o f") 'helm-open-github-from-file) +(global-set-key (kbd "C-c o c") 'helm-open-github-from-commit) +(global-set-key (kbd "C-c o i") 'helm-open-github-from-issues) +(global-set-key (kbd "C-c o p") 'helm-open-github-from-pull-requests) + + +(provide 'siren-helm) diff --git a/modules/siren-helpers.el b/modules/siren-helpers.el new file mode 100644 index 0000000..486f6a7 --- /dev/null +++ b/modules/siren-helpers.el @@ -0,0 +1,107 @@ +;; +;; helpers +;; + +;; +;; Duplicate Line +;; - from: http://tuxicity.se/emacs/elisp/2010/03/11/duplicate-current-line-or-region-in-emacs.html +;; + +(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. However, if +there's a region, all lines that region covers will be duplicated." + (interactive "p") + (let (beg end (origin (point))) + (if (and mark-active (> (point) (mark))) + (exchange-point-and-mark)) + (setq beg (line-beginning-position)) + (if mark-active + (exchange-point-and-mark)) + (setq end (line-end-position)) + (let ((region (buffer-substring-no-properties beg end))) + (dotimes (i arg) + (goto-char end) + (newline) + (insert region) + (setq end (point))) + (goto-char (+ origin (* (length region) arg) arg))))) + + +;; +;; Align Equal Signs +;; + +(defun align-region-to-equals (begin end) + "Align region to equal signs" + (interactive "r") + (align-regexp begin end "\\(\\s-*\\)=" 1 1 )) + +(defun align-region-to-opening-brace (begin end) + "Align region to equal signs" + (interactive "r") + (align-regexp begin end "\\(\\s-*\\){" 1 1 )) + + +;; +;; Yank Pop Forwards +;; + +(defun yank-pop-forwards (arg) + (interactive "p") + (yank-pop (- arg))) + + +;; +;; Window Switching +;; + +(defun other-window-reverse () + "Switch to the previous window" + (interactive) + (other-window -1)) + + +;; +;; HideShow mode helpers +;; - from: http://www.emacswiki.org/emacs/HideShow +;; +(defun toggle-selective-display (column) + (interactive "P") + (set-selective-display + (or column + (unless selective-display + (1+ (current-column)))))) + +(defun toggle-hiding (column) + (interactive "P") + (if hs-minor-mode + (if (condition-case nil + (hs-toggle-hiding) + (error t)) + (hs-show-all)) + (toggle-selective-display column))) + + +;; +;; File and Buffer Renaming +;; - from: http://emacsredux.com/blog/2013/05/04/rename-file-and-buffer/ +;; + +(defun rename-file-and-buffer () + "Rename the current buffer and file it is visiting." + (interactive) + (let ((filename (buffer-file-name))) + (if (not (and filename (file-exists-p filename))) + (message "Buffer is not visiting a file!") + (let ((new-name (read-file-name "New name: " filename))) + (cond + ((vc-backend filename) (vc-rename-file filename new-name)) + (t + (rename-file filename new-name t) + (rename-buffer new-name) + (set-visited-file-name new-name) + (set-buffer-modified-p nil))))))) + + +(provide 'siren-helpers) \ No newline at end of file diff --git a/modules/siren-highlight-indentation.el b/modules/siren-highlight-indentation.el new file mode 100644 index 0000000..bf6a0f1 --- /dev/null +++ b/modules/siren-highlight-indentation.el @@ -0,0 +1,12 @@ +;; +;; highlight-indentation +;; + +(siren-require-packages '(highlight-indentation)) + +(require 'highlight-indentation) +(diminish 'highlight-indentation-mode) +(diminish 'highlight-indentation-current-column-mode) + + +(provide 'siren-highlight-indentation) diff --git a/modules/siren-ido.el b/modules/siren-ido.el new file mode 100644 index 0000000..2f483e9 --- /dev/null +++ b/modules/siren-ido.el @@ -0,0 +1,36 @@ +;; +;; ido relateed +;; + +(siren-require-packages '(ido-ubiquitous ido-vertical-mode smex)) + +(require 'ido) +(require 'ido-ubiquitous) +(require 'ido-vertical-mode) + +(setq ido-enable-prefix nil + ido-enable-flex-matching t + ido-create-new-buffer 'always + ido-use-filename-at-point 'guess + ido-max-prospects 10 + ido-save-directory-list-file (expand-file-name "ido.hist" siren-savefile-dir) + ido-default-file-method 'selected-window + ido-auto-merge-work-directories-length -1 + ido-vertical-define-keys "C-n-C-p-up-down-left-right") + +(ido-mode +1) +(ido-ubiquitous-mode +1) +(ido-vertical-mode +1) + +;; disable ido faces to see flx highlights +(setq ido-use-faces nil) + +;;; smex, remember recently and most frequently used commands +(require 'smex) +(setq smex-save-file (expand-file-name ".smex-items" siren-savefile-dir)) +(smex-initialize) +(global-set-key (kbd "M-x") 'smex) +(global-set-key (kbd "M-X") 'smex-major-mode-commands) + + +(provide 'siren-ido) \ No newline at end of file diff --git a/modules/siren-linum.el b/modules/siren-linum.el new file mode 100644 index 0000000..d1643d5 --- /dev/null +++ b/modules/siren-linum.el @@ -0,0 +1,14 @@ +;; +;; linum +;; + +;; Customize line numbers - In gui mode the fringe is the spacer between line +;; numbers and code, while in console mode we add an extra space for it. +(if window-system (setq linum+-dynamic-format " %%%dd") + (setq linum+-dynamic-format " %%%dd ")) + +(eval-after-load "linum+" '(progn (setq linum-format 'dynamic))) + +(require 'linum+) + +(provide 'siren-linum) diff --git a/modules/siren-lisp.el b/modules/siren-lisp.el new file mode 100644 index 0000000..3305c48 --- /dev/null +++ b/modules/siren-lisp.el @@ -0,0 +1,34 @@ +;; +;; lisp +;; + +(require 'siren-programming) +(siren-require-packages '(rainbow-delimiters)) + +;; Lisp configuration +(define-key read-expression-map (kbd "TAB") 'completion-at-point) + +;; wrap keybindings +(define-key lisp-mode-shared-map (kbd "M-(") (siren-wrap-with "(")) +;; FIXME: Pick terminal-friendly binding. +;;(define-key lisp-mode-shared-map (kbd "M-[") (siren-wrap-with "[")) +(define-key lisp-mode-shared-map (kbd "M-\"") (siren-wrap-with "\"")) + +;; a great lisp coding hook +(defun siren-lisp-coding-defaults () + ;; (smartparens-strict-mode +1) + (rainbow-delimiters-mode +1) + ) + +(setq siren-lisp-coding-hook 'siren-lisp-coding-defaults) + +;; interactive modes don't need whitespace checks +(defun siren-interactive-lisp-coding-defaults () + ;; (smartparens-strict-mode +1) + (rainbow-delimiters-mode +1) + (whitespace-mode -1)) + +(setq siren-interactive-lisp-coding-hook 'siren-interactive-lisp-coding-defaults) + + +(provide 'siren-lisp) diff --git a/modules/siren-magit.el b/modules/siren-magit.el new file mode 100644 index 0000000..c4d8284 --- /dev/null +++ b/modules/siren-magit.el @@ -0,0 +1,46 @@ +;; +;; magit +;; + + +(siren-require-packages '(magit)) + +(require 'siren-fci) +(require 'magit) + +(setq magit-completing-read-function 'magit-ido-completing-read) +(setq magit-status-buffer-switch-function 'switch-to-buffer) +(setq magit-bury-buffer-function 'magit-mode-quit-window) +(setq magit-default-tracking-name-function + 'magit-default-tracking-name-branch-only) +(setq magit-repository-directories + (quote ("~/Projects" "~/src" "~/.emacs.d" "~/.dotfiles"))) + +(global-set-key (kbd "C-x g") 'magit-status) +(defalias 'bl 'magit-blame) + +;; Configure magit-mode +(defun siren-magit-mode-defaults () + ;; (linum-mode t) ;; Causes magit to freeze sometimes + ) + +(setq siren-magit-mode-hook 'siren-magit-mode-defaults) + +(add-hook 'magit-mode-hook (lambda () (run-hooks 'siren-magit-mode-hook))) + +;; Configure git-commit-mode +(defun siren-git-commit-mode-defaults () + (subword-mode +1) + (setq tab-width 2) + (flyspell-mode) + (linum-mode t) + (auto-fill-mode) + (subword-mode)) + +(setq siren-git-commit-mode-hook 'siren-git-commit-mode-defaults) + +(add-hook 'git-commit-mode-hook (lambda () + (run-hooks 'siren-git-commit-mode-hook))) + + +(provide 'siren-magit) diff --git a/modules/siren-makefile.el b/modules/siren-makefile.el new file mode 100644 index 0000000..b51babb --- /dev/null +++ b/modules/siren-makefile.el @@ -0,0 +1,21 @@ +;; +;; makefile +;; + +(require 'siren-programming) + +(defun siren-makefile-mode-defaults () + (siren-prog-mode-defaults) + (subword-mode) + (setq tab-width 4) + (setq highlight-indentation-offset 4) + (highlight-indentation-mode) + (highlight-indentation-current-column-mode)) + +(setq siren-makefile-mode-hook 'siren-makefile-mode-defaults) + +(add-hook 'makefile-mode-hook (lambda () + (run-hooks 'siren-makefile-mode-hook))) + + +(provide 'siren-makefile) diff --git a/modules/siren-markdown.el b/modules/siren-markdown.el new file mode 100644 index 0000000..2e7e8fe --- /dev/null +++ b/modules/siren-markdown.el @@ -0,0 +1,32 @@ +;; +;; sass +;; + +(siren-require-packages '(markdown-mode)) + +(require 'markdown-mode) + +(setq markdown-command "redcarpet") + +(setq auto-mode-alist (cons '("\\.md" . markdown-mode) auto-mode-alist)) +(setq auto-mode-alist (cons '("\\.mkd" . markdown-mode) auto-mode-alist)) +(setq auto-mode-alist (cons '("\\.mkdn" . markdown-mode) auto-mode-alist)) +(setq auto-mode-alist (cons '("\\.mdown" . markdown-mode) auto-mode-alist)) +(setq auto-mode-alist (cons '("\\.markdown" . markdown-mode) auto-mode-alist)) + +(defun siren-markdown-mode-defaults () + (setq whitespace-action nil) + (setq fill-column 80) + (fci-mode) + (linum-mode t) + (flyspell-mode) + (auto-fill-mode) + (subword-mode) + (define-key markdown-mode-map (kbd "C-c p") 'markdown-preview)) + +(setq siren-markdown-mode-hook 'siren-markdown-mode-defaults) + +(add-hook 'markdown-mode-hook (lambda () (run-hooks 'siren-markdown-mode-hook))) + + +(provide 'siren-markdown) diff --git a/modules/siren-move-beginning-of-line.el b/modules/siren-move-beginning-of-line.el new file mode 100644 index 0000000..597a4cd --- /dev/null +++ b/modules/siren-move-beginning-of-line.el @@ -0,0 +1,34 @@ +;; +;; move-beginning-of-line +;; + +;; Borrowed from: +;; - http://emacsredux.com/blog/2013/05/22/smarter-navigation-to-the-beginning-of-a-line/ +(defun siren-move-beginning-of-line (arg) + "Move point back to indentation of beginning of line. + +Move point to the first non-whitespace character on this line. +If point is already there, move to the beginning of the line. +Effectively toggle between the first non-whitespace character and +the beginning of the line. + +If ARG is not nil or 1, move forward ARG - 1 lines first. If +point reaches the beginning or end of the buffer, stop there." + (interactive "^p") + (setq arg (or arg 1)) + + ;; Move lines first + (when (/= arg 1) + (let ((line-move-visual nil)) + (forward-line (1- arg)))) + + (let ((orig-point (point))) + (back-to-indentation) + (when (= orig-point (point)) + (move-beginning-of-line 1)))) + +(global-set-key [remap move-beginning-of-line] + 'siren-move-beginning-of-line) + + +(provide 'siren-move-beginning-of-line) diff --git a/modules/siren-multiple-cursors.el b/modules/siren-multiple-cursors.el new file mode 100644 index 0000000..84b8bdf --- /dev/null +++ b/modules/siren-multiple-cursors.el @@ -0,0 +1,23 @@ +;; +;; multiple-cursors +;; + +(siren-require-packages '(multiple-cursors)) + +(require 'multiple-cursors) +(setq mc/edit-lines-empty-lines 'ignore) + +(global-set-key (kbd "C-x C-@") 'mc/edit-lines) ;; Terminal +(global-set-key (kbd "C-x C-SPC") 'mc/edit-lines) ;; GUI + +(global-set-key (kbd "M-/") 'mc/mark-next-like-this) +(global-set-key (kbd "M-m") 'mc/mark-previous-like-this) +(global-set-key (kbd "C-c M-/") 'mc/mark-all-like-this) +(global-set-key (kbd "M-RET") 'set-rectangular-region-anchor) + +;; Make alt- add additional cursors +(global-unset-key (kbd "M-")) ;; must unset key first +(global-set-key (kbd "M-") 'mc/add-cursor-on-click) + + +(provide 'siren-multiple-cursors) \ No newline at end of file diff --git a/modules/siren-neotree.el b/modules/siren-neotree.el new file mode 100644 index 0000000..964d3b7 --- /dev/null +++ b/modules/siren-neotree.el @@ -0,0 +1,10 @@ +;; +;; neotree +;; + +(siren-require-packages '(neotree)) + +(require 'neotree) +;; (global-set-key (kbd "C-x p") 'neotree-open) + +(provide 'siren-neotree) diff --git a/modules/siren-perspective.el b/modules/siren-perspective.el new file mode 100644 index 0000000..1694921 --- /dev/null +++ b/modules/siren-perspective.el @@ -0,0 +1,37 @@ +;; +;; perspective +;; + +(siren-require-packages '(perspective)) + +(require 'perspective) + +(define-key persp-mode-map (kbd "C-z") perspective-map) + +(define-key persp-mode-map (kbd "C-z s") 'persp-switch) +(define-key persp-mode-map (kbd "C-z C-s") 'persp-switch) +(define-key persp-mode-map (kbd "C-z b") 'persp-switch) +(define-key persp-mode-map (kbd "C-z C-b") 'persp-switch) + +(define-key persp-mode-map (kbd "C-z c") 'persp-remove-buffer) +(define-key persp-mode-map (kbd "C-z C-c") 'persp-remove-buffer) + +(define-key persp-mode-map (kbd "C-z k") 'persp-kill) +(define-key persp-mode-map (kbd "C-z C-k") 'persp-kill) + +(define-key persp-mode-map (kbd "C-z r") 'persp-rename) +(define-key persp-mode-map (kbd "C-z C-r") 'persp-rename) + +(define-key persp-mode-map (kbd "C-z a") 'persp-add-buffer) +(define-key persp-mode-map (kbd "C-z C-a") 'persp-add-buffer) + +(define-key persp-mode-map (kbd "C-z i") 'persp-import) +(define-key persp-mode-map (kbd "C-z C-i") 'persp-import) + +(define-key persp-mode-map (kbd "C-z n") 'persp-next) +(define-key persp-mode-map (kbd "C-z C-n") 'persp-next) +(define-key persp-mode-map (kbd "C-z p") 'persp-prev) +(define-key persp-mode-map (kbd "C-z C-p") 'persp-prev) + + +(provide 'siren-perspective) \ No newline at end of file diff --git a/modules/siren-phi-search.el b/modules/siren-phi-search.el new file mode 100644 index 0000000..e6b3f3e --- /dev/null +++ b/modules/siren-phi-search.el @@ -0,0 +1,12 @@ +;; +;; phi-search +;; + +(siren-require-packages '(phi-search)) + +(require 'phi-search) +(global-set-key (kbd "C-s") 'phi-search) +(global-set-key (kbd "C-r") 'phi-search-backward) + + +(provide 'siren-phi-search) \ No newline at end of file diff --git a/modules/siren-programming.el b/modules/siren-programming.el new file mode 100644 index 0000000..e37942a --- /dev/null +++ b/modules/siren-programming.el @@ -0,0 +1,32 @@ +;; +;; programming +;; + +(require 'siren-fci) +(require 'siren-flycheck) +(require 'siren-smartparens) +(require 'siren-highlight-indentation) + +(defun siren-prog-mode-defaults () + "Default coding hook, useful with any programming language." + (setq fill-column 80) + (linum-mode t) + (flyspell-prog-mode) + (fci-mode) + (smartparens-mode +1) + (setq whitespace-action (quote (auto-cleanup))) + (visual-line-mode +1) + (whitespace-mode +1)) + +(setq siren-prog-mode-hook 'siren-prog-mode-defaults) + +(add-hook 'prog-mode-hook (lambda () + (run-hooks 'siren-prog-mode-hook))) + +;; enable on-the-fly syntax checking +(if (fboundp 'global-flycheck-mode) + (global-flycheck-mode +1) + (add-hook 'prog-mode-hook 'flycheck-mode)) + + +(provide 'siren-programming) diff --git a/modules/siren-project-explorer.el b/modules/siren-project-explorer.el new file mode 100644 index 0000000..1d49637 --- /dev/null +++ b/modules/siren-project-explorer.el @@ -0,0 +1,30 @@ +;; +;; project-explorer +;; + +(siren-require-packages '(project-explorer)) + +(require 'project-explorer) +(setq pe/follow-current t) +(setq pe/width 54) +(setq pe/cache-directory (expand-file-name + "project-explorer-cache" siren-savefile-dir)) + +(global-set-key (kbd "C-x p") 'project-explorer-open) + +;; Make Project Explorer open selected file in last used buffer +(setq pe/display-content-buffer-function + (lambda (buffer) + (let* (( last-buffer + (car (cl-remove 'project-explorer-mode + (buffer-list) + :key (apply-partially 'buffer-local-value + 'major-mode)))) + ( window (get-buffer-window last-buffer))) + (if window + (set-window-buffer window buffer) + (pe/show-buffer buffer))) + )) + + +(provide 'siren-project-explorer) diff --git a/modules/siren-projectile.el b/modules/siren-projectile.el new file mode 100644 index 0000000..8082133 --- /dev/null +++ b/modules/siren-projectile.el @@ -0,0 +1,51 @@ +;; +;; projectile +;; + +(siren-require-packages '(projectile)) + +(require 'projectile) +(setq projectile-completion-system 'ido) +(setq projectile-enable-caching nil) +(setq projectile-globally-ignored-directories + (quote (".idea" + ".eunit" + ".git" + ".hg" + ".fslckout" + ".bzr" + ".svn" + "_darcs" + "vendor/bundle" + "vendor/ruby" + "coverage" + "docs" + "doc" + "log" + "logs" + "tmp" + "Godeps" + "elpa" + "savefile"))) +(setq projectile-globally-ignored-files (quote ("TAGS" "*.log"))) +(setq projectile-sort-order 'recently-active) + +(setq projectile-cache-file (expand-file-name + "projectile.cache" siren-savefile-dir)) + +;; Bug lets projectile write to the file, but not read from it +;; (setq projectile-known-projects-file (expand-file-name +;; "projectile-bookmarks.eld" siren-savefile-dir)) + + +(projectile-global-mode t) + +;; Keybindings +(global-set-key (kbd "C-c C-b") 'projectile-ibuffer) +(global-set-key (kbd "C-x C-t") 'projectile-find-file) +(global-set-key (kbd "C-x t") 'projectile-find-test-file) +(global-set-key (kbd "C-x C-v") 'projectile-switch-to-buffer) +(global-set-key (kbd "C-c C-s") 'projectile-switch-project) + + +(provide 'siren-projectile) diff --git a/modules/siren-ruby.el b/modules/siren-ruby.el new file mode 100644 index 0000000..1370cbb --- /dev/null +++ b/modules/siren-ruby.el @@ -0,0 +1,83 @@ +;; +;; ruby +;; + +(require 'siren-programming) + +(siren-require-packages '(ruby-tools inf-ruby yari company-inf-ruby)) + +;; Force-load custom vendored ruby-mode fetched from: +;; - https://raw.github.com/ruby/ruby/trunk/misc/ruby-mode.el +(load (expand-file-name "ruby-mode.el" siren-vendor-dir)) + +;; Rake files are ruby, too, as are gemspecs, rackup files, and gemfiles. +(add-to-list 'auto-mode-alist '("\\.rake\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Rakefile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.gemspec\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.ru\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Gemfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Guardfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Capfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.cap\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.thor\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.rabl\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Thorfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Vagrantfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.jbuilder\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Podfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.podspec\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Puppetfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Berksfile\\'" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Appraisals\\'" . ruby-mode)) + +;; We never want to edit Rubinius bytecode +(add-to-list 'completion-ignored-extensions ".rbc") + +(define-key 'help-command (kbd "R") 'yari) + +;; Set up hs-mode (HideShow) for Ruby +(add-to-list 'hs-special-modes-alist + `(ruby-mode + ,(rx (or "def" "class" "module" "do")) ;; Block start + ,(rx (or "end")) ;; Block end + ,(rx (or "#" "=begin")) ;; Comment start + ruby-forward-sexp nil)) + +(eval-after-load 'company + '(add-to-list 'company-backends 'company-inf-ruby)) + +(eval-after-load 'ruby-mode + '(progn + (defun siren-ruby-mode-defaults () + (siren-prog-mode-defaults) + (inf-ruby-minor-mode +1) + (ruby-tools-mode +1) + (setq tab-width 2) + (hs-minor-mode 1) + (company-mode +1) + (subword-mode +1) + (highlight-indentation-mode) + (highlight-indentation-current-column-mode) + (setq ruby-deep-arglist nil) + (setq ruby-deep-indent-paren nil) + (setq c-tab-always-indent nil) + (setq ruby-use-encoding-map nil) + (define-key ruby-mode-map (kbd "C-j") 'newline-and-indent) + (define-key ruby-mode-map (kbd "RET") 'newline-and-indent) + (define-key ruby-mode-map (kbd "C-c C-h") 'toggle-hiding) + (define-key ruby-mode-map (kbd "C-c C-l") 'goto-line)) + + (setq siren-ruby-mode-hook 'siren-ruby-mode-defaults) + + (add-hook 'ruby-mode-hook (lambda () + (run-hooks 'siren-ruby-mode-hook))))) + +;; ;; Auto-complete when indenting +;; (defadvice ruby-indent-command (around ac-before-ruby-indent activate) +;; "Call `auto-complete' if text was recently entered" +;; (if (ac-trigger-command-p last-command) +;; (auto-complete) +;; ad-do-it)) + + +(provide 'siren-ruby) diff --git a/modules/siren-sass.el b/modules/siren-sass.el new file mode 100644 index 0000000..96c65a6 --- /dev/null +++ b/modules/siren-sass.el @@ -0,0 +1,19 @@ +;; +;; sass +;; + +(require 'siren-css) +(siren-require-packages '(sass-mode)) + +;; turn off annoying auto-compile on save +(setq sass-compile-at-save nil) + +(defun siren-sass-mode-defaults () + (siren-css-mode-defaults)) + +(setq siren-sass-mode-hook 'siren-sass-mode-defaults) + +(add-hook 'sass-mode-hook (lambda () (run-hooks 'siren-sass-mode-hook))) + + +(provide 'siren-sass) diff --git a/modules/siren-scroll-half-screen.el b/modules/siren-scroll-half-screen.el new file mode 100644 index 0000000..2ce8111 --- /dev/null +++ b/modules/siren-scroll-half-screen.el @@ -0,0 +1,17 @@ +;; +;; scroll-half-screen +;; + +;; Scroll half a screen when using scroll-up and scroll-down functions. +(defadvice scroll-up (around half-window activate) + (setq next-screen-context-lines + (max 1 (/ (1- (window-height (selected-window))) 2))) + ad-do-it) + +(defadvice scroll-down (around half-window activate) + (setq next-screen-context-lines + (max 1 (/ (1- (window-height (selected-window))) 2))) + ad-do-it) + + +(provide 'siren-scroll-half-screen) \ No newline at end of file diff --git a/modules/siren-scss.el b/modules/siren-scss.el new file mode 100644 index 0000000..3281aa8 --- /dev/null +++ b/modules/siren-scss.el @@ -0,0 +1,19 @@ +;; +;; scss +;; + +(require 'siren-css) +(siren-require-packages '(scss-mode)) + +;; turn off annoying auto-compile on save +(setq scss-compile-at-save nil) + +(defun siren-scss-mode-defaults () + (siren-css-mode-defaults)) + +(setq siren-scss-mode-hook 'siren-scss-mode-defaults) + +(add-hook 'scss-mode-hook (lambda () (run-hooks 'siren-scss-mode-hook))) + + +(provide 'siren-scss) diff --git a/modules/siren-sh.el b/modules/siren-sh.el new file mode 100644 index 0000000..ab69486 --- /dev/null +++ b/modules/siren-sh.el @@ -0,0 +1,26 @@ +;; +;; shell +;; + +(require 'siren-programming) + +(defun siren-sh-mode-defaults () + (siren-prog-mode-defaults) + + (subword-mode +1) + (setq tab-width 2) + (setq sh-basic-offset 2) + (setq sh-indentation 2) + (setq highlight-indentation-offset 2) + (highlight-indentation-mode) + (highlight-indentation-current-column-mode) + (setq whitespace-action (quote (auto-cleanup))) + (define-key sh-mode-map (kbd "RET") 'newline-and-indent)) + +(setq siren-sh-mode-hook 'siren-sh-mode-defaults) + +(add-hook 'sh-mode-hook (lambda () + (run-hooks 'siren-sh-mode-hook))) + + +(provide 'siren-sh) diff --git a/modules/siren-smartparens.el b/modules/siren-smartparens.el new file mode 100644 index 0000000..fab2c74 --- /dev/null +++ b/modules/siren-smartparens.el @@ -0,0 +1,26 @@ +;; +;; smartparens +;; + +(siren-require-packages '(smartparens)) + +;; smart pairing for all +(require 'smartparens-config) +(setq sp-base-key-bindings 'paredit) +(setq sp-autoskip-closing-pair 'always) +(setq sp-hybrid-kill-entire-symbol nil) +(custom-set-faces + '(sp-pair-overlay-face ((t (:inherit nil))))) + +(sp-pair "{" nil :post-handlers + '(((lambda (&rest _ignored) + (siren-smart-open-line-above)) "RET"))) + +(show-smartparens-global-mode +1) +(diminish 'smartparens-mode) + +;; Aliases +(defalias 'rw 'sp-rewrap-sexp) + + +(provide 'siren-smartparens) diff --git a/modules/siren-smex.el b/modules/siren-smex.el new file mode 100644 index 0000000..2ed3423 --- /dev/null +++ b/modules/siren-smex.el @@ -0,0 +1,20 @@ +;; +;; smex +;; + +(siren-require-packages '(smex)) + +;;; smex, remember recently and most frequently used commands +(require 'smex) +(setq smex-save-file (expand-file-name ".smex-items" siren-savefile-dir)) +(smex-initialize) + +;; Keybindings +(global-set-key (kbd "M-x") 'smex) +(global-set-key (kbd "M-X") 'smex-major-mode-commands) +(global-set-key (kbd "C-x C-m") 'smex) +(global-set-key (kbd "C-c C-m") 'smex) +(global-set-key (kbd "C-c C-c M-x") 'execute-extended-command) + + +(provide 'siren-smex) \ No newline at end of file diff --git a/modules/siren-text-manipulation.el b/modules/siren-text-manipulation.el new file mode 100644 index 0000000..840bae7 --- /dev/null +++ b/modules/siren-text-manipulation.el @@ -0,0 +1,61 @@ +;; +;; text-manipulation +;; + +(siren-require-packages '(move-text expand-region)) + +(require 'move-text) +(require 'expand-region) + +;; Various things shamelessly ripped from textmate.el: +;; - https://github.com/defunkt/textmate.el + +(defmacro allow-line-as-region-for-function (orig-function) +`(defun ,(intern (concat (symbol-name orig-function) "-or-line")) + () + ,(format "Like `%s', but acts on the current line if mark is not active." + orig-function) + (interactive) + (if mark-active + (call-interactively (function ,orig-function)) + (save-excursion + ;; define a region (temporarily) -- so any C-u prefixes etc. are preserved. + (beginning-of-line) + (set-mark (point)) + (end-of-line) + (call-interactively (function ,orig-function)))))) + +(unless (fboundp 'comment-or-uncomment-region-or-line) + (allow-line-as-region-for-function comment-or-uncomment-region)) + +(defun siren-shift-right (&optional arg) + "Shift the line or region to the ARG places to the right. +A place is considered `tab-width' character columns." + (interactive) + (let ((deactivate-mark nil) + (beg (or (and mark-active (region-beginning)) + (line-beginning-position))) + (end (or (and mark-active (region-end)) (line-end-position)))) + (indent-rigidly beg end (* (or arg 1) tab-width)))) + +(defun siren-shift-left (&optional arg) + "Shift the line or region to the ARG places to the left." + (interactive) + (siren-shift-right (* -1 (or arg 1)))) + + +;; Keybindings +(define-key global-map (kbd "M-p") 'move-text-up) +(define-key global-map (kbd "M-n") 'move-text-down) + +(global-set-key (kbd "C-c [") 'siren-shift-left) +(global-set-key (kbd "C-c ]") 'siren-shift-right) + +(global-set-key (kbd "C-c /") 'comment-or-uncomment-region-or-line) +(global-set-key (kbd "C-c C-/") 'comment-or-uncomment-region-or-line) + +(global-set-key (kbd "M-.") 'er/expand-region) +(global-set-key (kbd "M-,") 'er/contract-region) + + +(provide 'siren-text-manipulation) diff --git a/modules/siren-volatile-highlights.el b/modules/siren-volatile-highlights.el new file mode 100644 index 0000000..1c2bf08 --- /dev/null +++ b/modules/siren-volatile-highlights.el @@ -0,0 +1,12 @@ +;; +;; volatile highlights +;; + +(siren-require-packages '(volatile-highlights)) + +(require 'volatile-highlights) +(volatile-highlights-mode t) +(diminish 'volatile-highlights-mode) + + +(provide 'siren-volatile-highlights) diff --git a/modules/siren-window-management.el b/modules/siren-window-management.el new file mode 100644 index 0000000..14f66ee --- /dev/null +++ b/modules/siren-window-management.el @@ -0,0 +1,33 @@ +;; +;; window-management +;; + +(defun ignore-error-wrapper (fn) + "Funtion return new function that ignore errors. + The function wraps a function with `ignore-errors' macro." + (lexical-let ((fn fn)) + (lambda () + (interactive) + (ignore-errors + (funcall fn))))) + + +(siren-require-packages '(buffer-move)) + +(require 'windmove) +(require 'buffer-move) + +;; Navigate to windows +(global-set-key (kbd "M-k") (ignore-error-wrapper 'windmove-down)) +(global-set-key (kbd "M-i") (ignore-error-wrapper 'windmove-up)) +(global-set-key (kbd "M-j") (ignore-error-wrapper 'windmove-left)) +(global-set-key (kbd "M-l") (ignore-error-wrapper 'windmove-right)) + +;; Swap buffers between windows +(global-set-key (kbd "M-K") 'buf-move-down) +(global-set-key (kbd "M-I") 'buf-move-up) +(global-set-key (kbd "M-J") 'buf-move-left) +(global-set-key (kbd "M-L") 'buf-move-right) + + +(provide 'siren-window-management) \ No newline at end of file diff --git a/modules/siren-workgroups2.el b/modules/siren-workgroups2.el new file mode 100644 index 0000000..3d4ac10 --- /dev/null +++ b/modules/siren-workgroups2.el @@ -0,0 +1,11 @@ +;; +;; workgroups2 +;; + +(siren-require-packages '(workgroups2)) + +(require 'workgroups2) +(setq wg-prefix-key (kbd "C-z") + + +(provide 'siren-workgroups2) \ No newline at end of file diff --git a/modules/siren-yasnippet.el b/modules/siren-yasnippet.el new file mode 100644 index 0000000..ee18275 --- /dev/null +++ b/modules/siren-yasnippet.el @@ -0,0 +1,13 @@ +;; +;; yasnippet +;; + +(siren-require-packages '(yasnippet)) + +(require 'yasnippet) +(diminish 'yas-minor-mode) + +(yas/global-mode t) + + +(provide 'siren-yasnippet) diff --git a/siren-modules.el b/siren-modules.el new file mode 100644 index 0000000..7d59613 --- /dev/null +++ b/siren-modules.el @@ -0,0 +1,56 @@ +;; +;; siren modules setup +;; + +;; Modules +(require 'siren-aliases) +(require 'siren-avy) +(require 'siren-auto-complete) +(require 'siren-company) +(require 'siren-dired) +(require 'siren-exec-path-from-shell) +(require 'siren-frame-transparency) +(require 'siren-full-ack) +(require 'siren-global-keybindings) +(require 'siren-github) +(require 'siren-goto-symbol) +(require 'siren-haml) +(require 'siren-helm) +(require 'siren-ido) +(require 'siren-linum) +(require 'siren-magit) +(require 'siren-move-beginning-of-line) +(require 'siren-multiple-cursors) +(require 'siren-phi-search) +(require 'siren-scroll-half-screen) +(require 'siren-smartparens) +(require 'siren-smex) +(require 'siren-text-manipulation) +(require 'siren-window-management) +(require 'siren-yasnippet) + +;; Project management +(require 'siren-projectile) +(require 'siren-project-explorer) +(require 'siren-ecb) ;; evil and slows down all of emacs +;; (require 'siren-neotree) + +;; Workspace management +(require 'siren-escreen) +;; (require 'siren-eslcreen) +;; (require 'siren-perspective) +;; (require 'siren-worksgroups2) + + +;; ;; Languages +(require 'siren-coffee) +(require 'siren-css) +(require 'siren-cucumber) +(require 'siren-emacs-lisp) +(require 'siren-go) +(require 'siren-makefile) +(require 'siren-markdown) +(require 'siren-ruby) +(require 'siren-sass) +(require 'siren-scss) +(require 'siren-sh) diff --git a/siren-theme.el b/siren-theme.el new file mode 100644 index 0000000..bcefc33 --- /dev/null +++ b/siren-theme.el @@ -0,0 +1,7 @@ +;; +;; siren theme setup +;; + +(if window-system + (require 'siren-theme-twilight-anti-bright) + (require 'siren-theme-tomorrow-night-paradise)) \ No newline at end of file diff --git a/themes/siren-theme-tomorrow-night-paradise.el b/themes/siren-theme-tomorrow-night-paradise.el new file mode 100644 index 0000000..4b76fd9 --- /dev/null +++ b/themes/siren-theme-tomorrow-night-paradise.el @@ -0,0 +1,8 @@ +;; +;; tomorrow-night-paradise-theme +;; + +(require 'tomorrow-night-paradise-theme) + + +(provide 'siren-theme-tomorrow-night-paradise) \ No newline at end of file diff --git a/themes/siren-theme-twilight-anti-bright.el b/themes/siren-theme-twilight-anti-bright.el new file mode 100644 index 0000000..442657b --- /dev/null +++ b/themes/siren-theme-twilight-anti-bright.el @@ -0,0 +1,10 @@ +;; +;; twilight-anti-bright-theme +;; + +(siren-require-packages '(twilight-anti-bright-theme twilight-bright-theme)) + +(require 'twilight-anti-bright-theme) + + +(provide 'siren-theme-twilight-anti-bright) \ No newline at end of file diff --git a/vendor/linum+.el b/vendor/linum+.el new file mode 100644 index 0000000..2b10c1d --- /dev/null +++ b/vendor/linum+.el @@ -0,0 +1,158 @@ +;;; linum+.el --- Extension of linum + +;; Copyright (C) 2010 ahei + +;; Author: ahei +;; Keywords: line number +;; URL: http://code.google.com/p/dea/source/browse/trunk/my-lisps/linum%2B.el +;; Time-stamp: <2010-04-08 10:55:43 Thursday by ahei> + +;; This file 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, +;; or (at your option) any later version. + +;; This file 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 GNU Emacs; see the file COPYING. If not, +;; write to the Free Software Foundation, Inc., 51 Franklin +;; Street, Fifth Floor, Boston, MA 02110-1301, USA. + +;;; Commentary: +;; +;; This extension of linum can smart control width of line number +;; displayed, If visible line number of current buffer is from 1 +;; to 50, then width of line number is 2, and visible line number +;; of current buffer is from 100 to 150, then width of line +;; number is 3. and use it, you can customize line number format +;; with linum+-dynamic-format even if linum-format is 'dynamic. +;; Its screenshots is +;; http://emacser.com/screenshots/linum+/linum+1.png and +;; http://emacser.com/screenshots/linum+/linum+2.png . For more +;; details, see article Use linum+ smart display line number +;; http://emacser.com/linum-plus.htm + +;;; Installation: +;; +;; Copy linum+.el to your load-path and add to your .emacs: +;; +;; (require 'linum+) +;; +;; then use M-x linum-mode to turn on line number displaying + +;;; History: +;; +;; 2010-04-04 +;; * Add more format control for linum-format +;; 2010-4-1 +;; * initial version 1.0. + +;;; Code: + +(require 'linum) + +(defgroup linum+ nil + "Extension of `linum-mode'." + :prefix "linum+-") + +;;;###autoload +(defcustom linum-format 'smart + "Format used to display line numbers. + ++ Either a format string like \"%7d\", ++ or `smart' to smart adapt the width by current max visible line number. ++ or `dynamic' to adapt the width as needed, ++ or a vector with one string element which uesed to generate + line number format by `format' with argument max visible line number + of current buffer, see example `linum+-smart-format' ++ or a list with one string element which uesed to generate + line number format by `format' with argument max line number of current buffer, + see example `linum+-dynamic-format' ++ or a function that is called with a line number as its + argument and should evaluate to a string to be shown on that line. + +See also `linum-before-numbering-hook'." + :group 'linum + :type 'sexp) + +(setq linum-format 'smart) + +;;;###autoload +(defcustom linum+-dynamic-format "%%%dd|" + "Format used to generate line number format when `linum-format' is `dynamic'." + :group 'linum+ + :type 'sexp) + +;;;###autoload +(defcustom linum+-smart-format "%%%dd|" + "Format used to generate line number format when `linum-format' is `smart'." + :group 'linum+ + :type 'sexp) + +;;;###autoload +(defun linum+-generate-linum-format (format-type limit) + "Generate line number format by FORMAT-TYPE, LIMIT is `window-end' of win." + (cond ((stringp format-type) format-type) + ((or (listp format-type) (vectorp format-type) + (eq format-type 'dynamic) (eq format-type 'smart)) + (let* ((dynamic-width (or (vectorp format-type) (eq format-type 'smart))) + (old-format + (if (eq format-type 'dynamic) + linum+-dynamic-format + (if (eq format-type 'smart) + linum+-smart-format + format-type))) + (w (length + (number-to-string + (line-number-at-pos (if dynamic-width limit (point-max)))))) + (new-format + (if (listp old-format) + (car old-format) + (if (vectorp old-format) + (aref old-format 0) + old-format)))) + (format new-format w))))) + +;;;###autoload +(defun linum-update-window (win) + "Update line numbers for the portion visible in window WIN." + (goto-char (window-start win)) + (let* ((line (line-number-at-pos)) + (limit (window-end win t)) + (fmt (linum+-generate-linum-format linum-format limit)) + (width 0)) + (run-hooks 'linum-before-numbering-hook) + ;; Create an overlay (or reuse an existing one) for each + ;; line visible in this window, if necessary. + (while (and (not (eobp)) (<= (point) limit)) + (let* ((str (if fmt + (propertize (format fmt line) 'face 'linum) + (funcall linum-format line))) + (visited (catch 'visited + (dolist (o (overlays-in (point) (point))) + (when (equal-including-properties + (overlay-get o 'linum-str) str) + (unless (memq o linum-overlays) + (push o linum-overlays)) + (setq linum-available (delq o linum-available)) + (throw 'visited t)))))) + (setq width (max width (length str))) + (unless visited + (let ((ov (if (null linum-available) + (make-overlay (point) (point)) + (move-overlay (pop linum-available) (point) (point))))) + (push ov linum-overlays) + (overlay-put ov 'before-string + (propertize " " 'display `((margin left-margin) ,str))) + (overlay-put ov 'linum-str str)))) + (forward-line) + (setq line (1+ line))) + (set-window-margins win width))) + +(provide 'linum+) + +;;; linum+.el ends here diff --git a/vendor/ruby-mode.el b/vendor/ruby-mode.el new file mode 100644 index 0000000..026f541 --- /dev/null +++ b/vendor/ruby-mode.el @@ -0,0 +1,1584 @@ +;;; ruby-mode.el --- Major mode for editing Ruby files + +;; Copyright (C) 1994, 1995, 1996 1997, 1998, 1999, 2000, 2001, +;; 2002,2003, 2004, 2005, 2006, 2007, 2008 +;; Free Software Foundation, Inc. + +;; Authors: Yukihiro Matsumoto, Nobuyoshi Nakada +;; URL: http://www.emacswiki.org/cgi-bin/wiki/RubyMode +;; Created: Fri Feb 4 14:49:13 JST 1994 +;; Keywords: languages ruby +;; Version: 0.9 + +;; This file is not part of GNU Emacs. However, a newer version of +;; ruby-mode is included in recent releases of GNU Emacs (version 23 +;; and up), but the new version is not guaranteed to be compatible +;; with older versions of Emacs or XEmacs. This file is the last +;; version that aims to keep this compatibility. + +;; You can also get the latest version from the Emacs Lisp Package +;; Archive: http://tromey.com/elpa + +;; This file 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. + +;; It 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 it. If not, see . + +;;; Commentary: + +;; Provides font-locking, indentation support, and navigation for Ruby code. +;; +;; If you're installing manually, you should add this to your .emacs +;; file after putting it on your load path: +;; +;; (autoload 'ruby-mode "ruby-mode" "Major mode for ruby files" t) +;; (add-to-list 'auto-mode-alist '("\\.rb$" . ruby-mode)) +;; (add-to-list 'interpreter-mode-alist '("ruby" . ruby-mode)) +;; + +;;; Code: + +(defconst ruby-mode-revision "$Revision$" + "Ruby mode revision string.") + +(defconst ruby-mode-version + (and (string-match "[0-9.]+" ruby-mode-revision) + (substring ruby-mode-revision (match-beginning 0) (match-end 0))) + "Ruby mode version number.") + +(defconst ruby-keyword-end-re + (if (string-match "\\_>" "ruby") + "\\_>" + "\\>")) + +(defconst ruby-block-beg-keywords + '("class" "module" "def" "if" "unless" "case" "while" "until" "for" "begin" "do") + "Keywords at the beginning of blocks.") + +(defconst ruby-block-beg-re + (regexp-opt ruby-block-beg-keywords) + "Regexp to match the beginning of blocks.") + +(defconst ruby-non-block-do-re + (concat (regexp-opt '("while" "until" "for" "rescue") t) ruby-keyword-end-re) + "Regexp to match") + +(defconst ruby-indent-beg-re + (concat "\\(\\s *" (regexp-opt '("class" "module" "def") t) "\\)\\|" + (regexp-opt '("if" "unless" "case" "while" "until" "for" "begin"))) + "Regexp to match where the indentation gets deeper.") + +(defconst ruby-modifier-beg-keywords + '("if" "unless" "while" "until") + "Modifiers that are the same as the beginning of blocks.") + +(defconst ruby-modifier-beg-re + (regexp-opt ruby-modifier-beg-keywords) + "Regexp to match modifiers same as the beginning of blocks.") + +(defconst ruby-modifier-re + (regexp-opt (cons "rescue" ruby-modifier-beg-keywords)) + "Regexp to match modifiers.") + +(defconst ruby-block-mid-keywords + '("then" "else" "elsif" "when" "rescue" "ensure") + "Keywords where the indentation gets shallower in middle of block statements.") + +(defconst ruby-block-mid-re + (regexp-opt ruby-block-mid-keywords) + "Regexp to match where the indentation gets shallower in middle of block statements.") + +(defconst ruby-block-op-keywords + '("and" "or" "not") + "Block operators.") + +(defconst ruby-block-hanging-re + (regexp-opt (append ruby-modifier-beg-keywords ruby-block-op-keywords)) + "Regexp to match hanging block modifiers.") + +(defconst ruby-block-end-re "\\_") + +(defconst ruby-here-doc-beg-re + "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)") + +(defconst ruby-here-doc-end-re + "^\\([ \t]+\\)?\\(.*\\)\\(.\\)$") + +(defun ruby-here-doc-end-match () + (concat "^" + (if (match-string 2) "[ \t]*" nil) + (regexp-quote + (or (match-string 4) + (match-string 5) + (match-string 6))))) + +(defun ruby-here-doc-beg-match () + (let ((contents (concat + (regexp-quote (concat (match-string 2) (match-string 3))) + (if (string= (match-string 3) "_") "\\B" "\\b")))) + (concat "<<" + (let ((match (match-string 1))) + (if (and match (> (length match) 0)) + (concat "\\(?:-\\([\"']?\\)\\|\\([\"']\\)" (match-string 1) "\\)" + contents "\\(\\1\\|\\2\\)") + (concat "-?\\([\"']\\|\\)" contents "\\1")))))) + +(defconst ruby-delimiter + (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\_<\\(" + ruby-block-beg-re + "\\)\\_>\\|" ruby-block-end-re + "\\|^=begin\\|" ruby-here-doc-beg-re) + ) + +(defconst ruby-negative + (concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\>\\|" + ruby-block-end-re "\\|}\\|\\]\\)") + "Regexp to match where the indentation gets shallower.") + +(defconst ruby-operator-chars "-,.+*/%&|^~=<>:") +(defconst ruby-operator-re (concat "[" ruby-operator-chars "]")) + +(defconst ruby-symbol-chars "a-zA-Z0-9_") +(defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]")) + +(defvar ruby-mode-abbrev-table nil + "Abbrev table in use in ruby-mode buffers.") + +(define-abbrev-table 'ruby-mode-abbrev-table ()) + +(defvar ruby-mode-map nil "Keymap used in ruby mode.") + +(if ruby-mode-map + nil + (setq ruby-mode-map (make-sparse-keymap)) + (define-key ruby-mode-map "{" 'ruby-electric-brace) + (define-key ruby-mode-map "}" 'ruby-electric-brace) + (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun) + (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun) + (define-key ruby-mode-map "\e\C-b" 'ruby-backward-sexp) + (define-key ruby-mode-map "\e\C-f" 'ruby-forward-sexp) + (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block) + (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block) + (define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun) + (define-key ruby-mode-map "\e\C-q" 'ruby-indent-exp) + (define-key ruby-mode-map "\t" 'ruby-indent-command) + (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end) + (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent) + (define-key ruby-mode-map "\C-c{" 'ruby-toggle-block) + (define-key ruby-mode-map "\C-c\C-u" 'uncomment-region)) + +(defvar ruby-mode-syntax-table nil + "Syntax table in use in ruby-mode buffers.") + +(if ruby-mode-syntax-table + () + (setq ruby-mode-syntax-table (make-syntax-table)) + (modify-syntax-entry ?\' "\"" ruby-mode-syntax-table) + (modify-syntax-entry ?\" "\"" ruby-mode-syntax-table) + (modify-syntax-entry ?\` "\"" ruby-mode-syntax-table) + (modify-syntax-entry ?# "<" ruby-mode-syntax-table) + (modify-syntax-entry ?\n ">" ruby-mode-syntax-table) + (modify-syntax-entry ?\\ "\\" ruby-mode-syntax-table) + (modify-syntax-entry ?$ "." ruby-mode-syntax-table) + (modify-syntax-entry ?? "_" ruby-mode-syntax-table) + (modify-syntax-entry ?_ "_" ruby-mode-syntax-table) + (modify-syntax-entry ?: "_" ruby-mode-syntax-table) + (modify-syntax-entry ?< "." ruby-mode-syntax-table) + (modify-syntax-entry ?> "." ruby-mode-syntax-table) + (modify-syntax-entry ?& "." ruby-mode-syntax-table) + (modify-syntax-entry ?| "." ruby-mode-syntax-table) + (modify-syntax-entry ?% "." ruby-mode-syntax-table) + (modify-syntax-entry ?= "." ruby-mode-syntax-table) + (modify-syntax-entry ?/ "." ruby-mode-syntax-table) + (modify-syntax-entry ?+ "." ruby-mode-syntax-table) + (modify-syntax-entry ?* "." ruby-mode-syntax-table) + (modify-syntax-entry ?- "." ruby-mode-syntax-table) + (modify-syntax-entry ?\; "." ruby-mode-syntax-table) + (modify-syntax-entry ?\( "()" ruby-mode-syntax-table) + (modify-syntax-entry ?\) ")(" ruby-mode-syntax-table) + (modify-syntax-entry ?\{ "(}" ruby-mode-syntax-table) + (modify-syntax-entry ?\} "){" ruby-mode-syntax-table) + (modify-syntax-entry ?\[ "(]" ruby-mode-syntax-table) + (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table) + ) + +(defcustom ruby-indent-tabs-mode nil + "*Indentation can insert tabs in ruby mode if this is non-nil." + :type 'boolean :group 'ruby) +(put 'ruby-indent-tabs-mode 'safe-local-variable 'booleanp) + +(defcustom ruby-indent-level 2 + "*Indentation of ruby statements." + :type 'integer :group 'ruby) +(put 'ruby-indent-level 'safe-local-variable 'integerp) + +(defcustom ruby-comment-column 32 + "*Indentation column of comments." + :type 'integer :group 'ruby) +(put 'ruby-comment-column 'safe-local-variable 'integerp) + +(defcustom ruby-deep-arglist t + "*Deep indent lists in parenthesis when non-nil. +Also ignores spaces after parenthesis when 'space." + :group 'ruby) +(put 'ruby-deep-arglist 'safe-local-variable 'booleanp) + +(defcustom ruby-deep-indent-paren '(?\( ?\[ ?\] t) + "*Deep indent lists in parenthesis when non-nil. t means continuous line. +Also ignores spaces after parenthesis when 'space." + :group 'ruby) + +(defcustom ruby-deep-indent-paren-style 'space + "Default deep indent style." + :options '(t nil space) :group 'ruby) + +(defcustom ruby-encoding-map + '((us-ascii . nil) ;; Do not put coding: us-ascii + (utf-8 . nil) ;; Do not put coding: utf-8 + (shift-jis . cp932) ;; Emacs charset name of Shift_JIS + (shift_jis . cp932) ;; MIME charset name of Shift_JIS + (japanese-cp932 . cp932)) ;; Emacs charset name of CP932 + "Alist to map encoding name from Emacs to Ruby. +Associating an encoding name with nil means it needs not be +explicitly declared in magic comment." + :type '(repeat (cons (symbol :tag "From") (symbol :tag "To"))) + :group 'ruby) + +(defcustom ruby-use-encoding-map t + "*Use `ruby-encoding-map' to set encoding magic comment if this is non-nil." + :type 'boolean :group 'ruby) + +(defvar ruby-indent-point nil "internal variable") + +(eval-when-compile (require 'cl)) +(defun ruby-imenu-create-index-in-block (prefix beg end) + (let ((index-alist '()) (case-fold-search nil) + name next pos decl sing) + (goto-char beg) + (while (re-search-forward "^\\s *\\(\\(class\\s +\\|\\(class\\s *<<\\s *\\)\\|module\\s +\\)\\([^\(<\n ]+\\)\\|\\(def\\|alias\\)\\s +\\([^\(\n ]+\\)\\)" end t) + (setq sing (match-beginning 3)) + (setq decl (match-string 5)) + (setq next (match-end 0)) + (setq name (or (match-string 4) (match-string 6))) + (setq pos (match-beginning 0)) + (cond + ((string= "alias" decl) + (if prefix (setq name (concat prefix name))) + (push (cons name pos) index-alist)) + ((string= "def" decl) + (if prefix + (setq name + (cond + ((string-match "^self\." name) + (concat (substring prefix 0 -1) (substring name 4))) + (t (concat prefix name))))) + (push (cons name pos) index-alist) + (ruby-accurate-end-of-block end)) + (t + (if (string= "self" name) + (if prefix (setq name (substring prefix 0 -1))) + (if prefix (setq name (concat (substring prefix 0 -1) "::" name))) + (push (cons name pos) index-alist)) + (ruby-accurate-end-of-block end) + (setq beg (point)) + (setq index-alist + (nconc (ruby-imenu-create-index-in-block + (concat name (if sing "." "#")) + next beg) index-alist)) + (goto-char beg)))) + index-alist)) + +(defun ruby-imenu-create-index () + (nreverse (ruby-imenu-create-index-in-block nil (point-min) nil))) + +(defun ruby-accurate-end-of-block (&optional end) + (let (state) + (or end (setq end (point-max))) + (while (and (setq state (apply 'ruby-parse-partial end state)) + (>= (nth 2 state) 0) (< (point) end))))) + +(defun ruby-mode-variables () + (set-syntax-table ruby-mode-syntax-table) + (setq show-trailing-whitespace t) + (setq local-abbrev-table ruby-mode-abbrev-table) + (make-local-variable 'indent-line-function) + (setq indent-line-function 'ruby-indent-line) + (make-local-variable 'require-final-newline) + (setq require-final-newline t) + (make-local-variable 'comment-start) + (setq comment-start "# ") + (make-local-variable 'comment-end) + (setq comment-end "") + (make-local-variable 'comment-column) + (setq comment-column ruby-comment-column) + (make-local-variable 'comment-start-skip) + (setq comment-start-skip "#+ *") + (setq indent-tabs-mode ruby-indent-tabs-mode) + (make-local-variable 'parse-sexp-ignore-comments) + (setq parse-sexp-ignore-comments t) + (make-local-variable 'parse-sexp-lookup-properties) + (setq parse-sexp-lookup-properties t) + (make-local-variable 'paragraph-start) + (setq paragraph-start (concat "$\\|" page-delimiter)) + (make-local-variable 'paragraph-separate) + (setq paragraph-separate paragraph-start) + (make-local-variable 'paragraph-ignore-fill-prefix) + (setq paragraph-ignore-fill-prefix t)) + +(defun ruby-mode-set-encoding () + "Insert or update a magic comment header with the proper encoding. +`ruby-encoding-map' is looked up to convert an encoding name from +Emacs to Ruby." + (let* ((nonascii + (save-excursion + (widen) + (goto-char (point-min)) + (re-search-forward "[^\0-\177]" nil t))) + (coding-system + (or coding-system-for-write + buffer-file-coding-system)) + (coding-system + (and coding-system + (coding-system-change-eol-conversion coding-system nil))) + (coding-system + (and coding-system + (or + (coding-system-get coding-system :mime-charset) + (let ((coding-type (coding-system-get coding-system :coding-type))) + (cond ((eq coding-type 'undecided) + (if nonascii + (or (and (coding-system-get coding-system :prefer-utf-8) + 'utf-8) + (coding-system-get default-buffer-file-coding-system :coding-type) + 'ascii-8bit))) + ((memq coding-type '(utf-8 shift-jis)) + coding-type) + (t coding-system)))))) + (coding-system + (or coding-system + 'us-ascii)) + (coding-system + (let ((cons (assq coding-system ruby-encoding-map))) + (if cons (cdr cons) coding-system))) + (coding-system + (and coding-system + (symbol-name coding-system)))) + (if coding-system + (save-excursion + (widen) + (goto-char (point-min)) + (if (looking-at "^#!") (beginning-of-line 2)) + (cond ((looking-at "\\s *#.*-\*-\\s *\\(en\\)?coding\\s *:\\s *\\([-a-z0-9_]*\\)\\s *\\(;\\|-\*-\\)") + (unless (string= (match-string 2) coding-system) + (goto-char (match-beginning 2)) + (delete-region (point) (match-end 2)) + (and (looking-at "-\*-") + (let ((n (skip-chars-backward " "))) + (cond ((= n 0) (insert " ") (backward-char)) + ((= n -1) (insert " ")) + ((forward-char))))) + (insert coding-system))) + ((looking-at "\\s *#.*coding\\s *[:=]")) + (t (when ruby-insert-encoding-magic-comment + (insert "# -*- coding: " coding-system " -*-\n")))))))) + +(defun ruby-current-indentation () + (save-excursion + (beginning-of-line) + (back-to-indentation) + (current-column))) + +(defun ruby-indent-line (&optional flag) + "Correct indentation of the current ruby line." + (ruby-indent-to (ruby-calculate-indent))) + +(defun ruby-indent-command () + (interactive) + (ruby-indent-line t)) + +(defun ruby-indent-to (x) + (if x + (let (shift top beg) + (and (< x 0) (error "invalid nest")) + (setq shift (current-column)) + (beginning-of-line) + (setq beg (point)) + (back-to-indentation) + (setq top (current-column)) + (skip-chars-backward " \t") + (if (>= shift top) (setq shift (- shift top)) + (setq shift 0)) + (if (and (bolp) + (= x top)) + (move-to-column (+ x shift)) + (move-to-column top) + (delete-region beg (point)) + (beginning-of-line) + (indent-to x) + (move-to-column (+ x shift)))))) + +(defun ruby-special-char-p (&optional pnt) + (setq pnt (or pnt (point))) + (let ((c (char-before pnt)) (b (and (< (point-min) pnt) (char-before (1- pnt))))) + (cond ((or (eq c ??) (eq c ?$))) + ((and (eq c ?:) (or (not b) (eq (char-syntax b) ? )))) + ((eq c ?\\) (eq b ??))))) + +(defun ruby-singleton-class-p () + (save-excursion + (forward-word -1) + (and (or (bolp) (not (eq (char-before (point)) ?_))) + (looking-at "class\\s *<<")))) + +(defun ruby-expr-beg (&optional option) + (save-excursion + (store-match-data nil) + (let ((space (skip-chars-backward " \t")) + (start (point))) + (cond + ((bolp) t) + ((progn + (forward-char -1) + (and (looking-at "\\?") + (or (eq (char-syntax (preceding-char)) ?w) + (ruby-special-char-p)))) + nil) + ((and (eq option 'heredoc) (< space 0)) + (not (progn (goto-char start) (ruby-singleton-class-p)))) + ((or (looking-at ruby-operator-re) + (looking-at "[\\[({,;]") + (and (looking-at "[!?]") + (or (not (eq option 'modifier)) + (bolp) + (save-excursion (forward-char -1) (looking-at "\\Sw$")))) + (and (looking-at ruby-symbol-re) + (skip-chars-backward ruby-symbol-chars) + (cond + ((looking-at (regexp-opt + (append ruby-block-beg-keywords + ruby-block-op-keywords + ruby-block-mid-keywords) + 'words)) + (goto-char (match-end 0)) + (not (looking-at "\\s_\\|[!?:]"))) + ((eq option 'expr-qstr) + (looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]")) + ((eq option 'expr-re) + (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]")) + (t nil))))))))) + +(defun ruby-forward-string (term &optional end no-error expand) + (let ((n 1) (c (string-to-char term)) + (re (if expand + (concat "[^\\]\\(\\\\\\\\\\)*\\([" term "]\\|\\(#{\\)\\)") + (concat "[^\\]\\(\\\\\\\\\\)*[" term "]")))) + (while (and (re-search-forward re end no-error) + (if (match-beginning 3) + (ruby-forward-string "}{" end no-error nil) + (> (setq n (if (eq (char-before (point)) c) + (1- n) (1+ n))) 0))) + (forward-char -1)) + (cond ((zerop n)) + (no-error nil) + ((error "unterminated string"))))) + +(defun ruby-deep-indent-paren-p (c &optional pos) + (cond ((save-excursion + (if pos (goto-char pos)) + (ruby-expr-beg)) + nil) + ((listp ruby-deep-indent-paren) + (let ((deep (assoc c ruby-deep-indent-paren))) + (cond (deep + (or (cdr deep) ruby-deep-indent-paren-style)) + ((memq c ruby-deep-indent-paren) + ruby-deep-indent-paren-style)))) + ((eq c ruby-deep-indent-paren) ruby-deep-indent-paren-style) + ((eq c ?\( ) ruby-deep-arglist))) + +(defun ruby-parse-partial (&optional end in-string nest depth pcol indent) + (or depth (setq depth 0)) + (or indent (setq indent 0)) + (when (re-search-forward ruby-delimiter end 'move) + (let ((pnt (point)) w re expand) + (goto-char (match-beginning 0)) + (cond + ((and (memq (char-before) '(?@ ?$)) (looking-at "\\sw")) + (goto-char pnt)) + ((looking-at "[\"`]") ;skip string + (cond + ((and (not (eobp)) + (ruby-forward-string (buffer-substring (point) (1+ (point))) end t t)) + nil) + (t + (setq in-string (point)) + (goto-char end)))) + ((looking-at "'") + (cond + ((and (not (eobp)) + (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" end t)) + nil) + (t + (setq in-string (point)) + (goto-char end)))) + ((looking-at "/=") + (goto-char pnt)) + ((looking-at "/") + (cond + ((and (not (eobp)) (ruby-expr-beg 'expr-re)) + (if (ruby-forward-string "/" end t t) + nil + (setq in-string (point)) + (goto-char end))) + (t + (goto-char pnt)))) + ((looking-at "%") + (cond + ((and (not (eobp)) + (ruby-expr-beg 'expr-qstr) + (not (looking-at "%=")) + (looking-at "%[QqrxWw]?\\([^a-zA-Z0-9 \t\n]\\)")) + (goto-char (match-beginning 1)) + (setq expand (not (memq (char-before) '(?q ?w)))) + (setq w (match-string 1)) + (cond + ((string= w "[") (setq re "][")) + ((string= w "{") (setq re "}{")) + ((string= w "(") (setq re ")(")) + ((string= w "<") (setq re "><")) + ((and expand (string= w "\\")) + (setq w (concat "\\" w)))) + (unless (cond (re (ruby-forward-string re end t expand)) + (expand (ruby-forward-string w end t t)) + (t (re-search-forward + (if (string= w "\\") + "\\\\[^\\]*\\\\" + (concat "[^\\]\\(\\\\\\\\\\)*" w)) + end t))) + (setq in-string (point)) + (goto-char end))) + (t + (goto-char pnt)))) + ((looking-at "\\?") ;skip ?char + (cond + ((and (ruby-expr-beg) + (looking-at "?\\(\\\\C-\\|\\\\M-\\)*\\\\?.")) + (goto-char (match-end 0))) + (t + (goto-char pnt)))) + ((looking-at "\\$") ;skip $char + (goto-char pnt) + (forward-char 1)) + ((looking-at "#") ;skip comment + (forward-line 1) + (goto-char (point)) + ) + ((looking-at "[\\[{(]") + (let ((deep (ruby-deep-indent-paren-p (char-after)))) + (if (and deep (or (not (eq (char-after) ?\{)) (ruby-expr-beg))) + (progn + (and (eq deep 'space) (looking-at ".\\s +[^# \t\n]") + (setq pnt (1- (match-end 0)))) + (setq nest (cons (cons (char-after (point)) (point)) nest)) + (setq pcol (cons (cons pnt depth) pcol)) + (setq depth 0)) + (setq nest (cons (cons (char-after (point)) pnt) nest)) + (setq depth (1+ depth)))) + (goto-char pnt) + ) + ((looking-at "[])}]") + (if (ruby-deep-indent-paren-p (matching-paren (char-after)) + (if nest + (cdr (nth 0 nest)) + (save-excursion + (forward-char) + (ruby-backward-sexp) + (point)))) + (setq depth (cdr (car pcol)) pcol (cdr pcol)) + (setq depth (1- depth))) + (setq nest (cdr nest)) + (goto-char pnt)) + ((looking-at ruby-block-end-re) + (if (or (and (not (bolp)) + (progn + (forward-char -1) + (setq w (char-after (point))) + (or (eq ?_ w) + (eq ?. w)))) + (progn + (goto-char pnt) + (setq w (char-after (point))) + (or (eq ?_ w) + (eq ?! w) + (eq ?? w)))) + nil + (setq nest (cdr nest)) + (setq depth (1- depth))) + (goto-char pnt)) + ((looking-at "def\\s +[^(\n;]*") + (if (or (bolp) + (progn + (forward-char -1) + (not (eq ?_ (char-after (point)))))) + (progn + (setq nest (cons (cons nil pnt) nest)) + (setq depth (1+ depth)))) + (goto-char (match-end 0))) + ((looking-at (concat "\\_<\\(" ruby-block-beg-re "\\)\\_>")) + (and + (save-match-data + (or (not (looking-at (concat "do" ruby-keyword-end-re))) + (save-excursion + (back-to-indentation) + (not (looking-at ruby-non-block-do-re))))) + (or (bolp) + (progn + (forward-char -1) + (setq w (char-after (point))) + (not (or (eq ?_ w) + (eq ?. w))))) + (goto-char pnt) + (setq w (char-after (point))) + (not (eq ?_ w)) + (not (eq ?! w)) + (not (eq ?? w)) + (not (eq ?: w)) + (skip-chars-forward " \t") + (goto-char (match-beginning 0)) + (or (not (looking-at ruby-modifier-re)) + (ruby-expr-beg 'modifier)) + (goto-char pnt) + (setq nest (cons (cons nil pnt) nest)) + (setq depth (1+ depth))) + (goto-char pnt)) + ((looking-at ":\\(['\"]\\)") + (goto-char (match-beginning 1)) + (ruby-forward-string (buffer-substring (match-beginning 1) (match-end 1)) end)) + ((looking-at ":\\([-,.+*/%&|^~<>]=?\\|===?\\|<=>\\|![~=]?\\)") + (goto-char (match-end 0))) + ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*[!?=]?\\)?") + (goto-char (match-end 0))) + ((or (looking-at "\\.\\.\\.?") + (looking-at "\\.[0-9]+") + (looking-at "\\.[a-zA-Z_0-9]+") + (looking-at "\\.")) + (goto-char (match-end 0))) + ((looking-at "^=begin") + (if (re-search-forward "^=end" end t) + (forward-line 1) + (setq in-string (match-end 0)) + (goto-char end))) + ((looking-at "<<") + (cond + ((and (ruby-expr-beg 'heredoc) + (looking-at "<<\\(-\\)?\\(\\([\"'`]\\)\\([^\n]+?\\)\\3\\|\\(?:\\sw\\|\\s_\\)+\\)")) + (setq re (regexp-quote (or (match-string 4) (match-string 2)))) + (if (match-beginning 1) (setq re (concat "\\s *" re))) + (let* ((id-end (goto-char (match-end 0))) + (line-end-position (save-excursion (end-of-line) (point))) + (state (list in-string nest depth pcol indent))) + ;; parse the rest of the line + (while (and (> line-end-position (point)) + (setq state (apply 'ruby-parse-partial + line-end-position state)))) + (setq in-string (car state) + nest (nth 1 state) + depth (nth 2 state) + pcol (nth 3 state) + indent (nth 4 state)) + ;; skip heredoc section + (if (re-search-forward (concat "^" re "$") end 'move) + (forward-line 1) + (setq in-string id-end) + (goto-char end)))) + (t + (goto-char pnt)))) + ((looking-at "^__END__$") + (goto-char pnt)) + ((looking-at ruby-here-doc-beg-re) + (if (re-search-forward (ruby-here-doc-end-match) + ruby-indent-point t) + (forward-line 1) + (setq in-string (match-end 0)) + (goto-char ruby-indent-point))) + (t + (error (format "bad string %s" + (buffer-substring (point) pnt) + )))))) + (list in-string nest depth pcol)) + +(defun ruby-parse-region (start end) + (let (state) + (save-excursion + (if start + (goto-char start) + (ruby-beginning-of-indent)) + (save-restriction + (narrow-to-region (point) end) + (while (and (> end (point)) + (setq state (apply 'ruby-parse-partial end state)))))) + (list (nth 0 state) ; in-string + (car (nth 1 state)) ; nest + (nth 2 state) ; depth + (car (car (nth 3 state))) ; pcol + ;(car (nth 5 state)) ; indent + ))) + +(defun ruby-indent-size (pos nest) + (+ pos (* (or nest 1) ruby-indent-level))) + +(defun ruby-calculate-indent (&optional parse-start) + (save-excursion + (beginning-of-line) + (let ((ruby-indent-point (point)) + (case-fold-search nil) + state bol eol begin op-end + (paren (progn (skip-syntax-forward " ") + (and (char-after) (matching-paren (char-after))))) + (indent 0)) + (if parse-start + (goto-char parse-start) + (ruby-beginning-of-indent) + (setq parse-start (point))) + (back-to-indentation) + (setq indent (current-column)) + (setq state (ruby-parse-region parse-start ruby-indent-point)) + (cond + ((nth 0 state) ; within string + (setq indent nil)) ; do nothing + ((car (nth 1 state)) ; in paren + (goto-char (setq begin (cdr (nth 1 state)))) + (let ((deep (ruby-deep-indent-paren-p (car (nth 1 state)) + (1- (cdr (nth 1 state)))))) + (if deep + (cond ((and (eq deep t) (eq (car (nth 1 state)) paren)) + (skip-syntax-backward " ") + (setq indent (1- (current-column)))) + ((eq deep 'space) + (goto-char (cdr (nth 1 state))) + (setq indent (1+ (current-column)))) + ((let ((s (ruby-parse-region (point) ruby-indent-point))) + (and (nth 2 s) (> (nth 2 s) 0) + (or (goto-char (cdr (nth 1 s))) t))) + (forward-word -1) + (setq indent (ruby-indent-size (current-column) (nth 2 state)))) + (t + (setq indent (current-column)) + (cond ((eq deep 'space)) + (paren (setq indent (1- indent))) + (t (setq indent (ruby-indent-size (1- indent) 1)))))) + (if (nth 3 state) (goto-char (nth 3 state)) + (goto-char parse-start) (back-to-indentation)) + (setq indent (ruby-indent-size (current-column) (nth 2 state)))) + (and (eq (car (nth 1 state)) paren) + (ruby-deep-indent-paren-p (matching-paren paren) + (1- (cdr (nth 1 state)))) + (search-backward (char-to-string paren)) + (setq indent (current-column))))) + ((and (nth 2 state) (> (nth 2 state) 0)) ; in nest + (if (null (cdr (nth 1 state))) + (error "invalid nest")) + (goto-char (cdr (nth 1 state))) + (forward-word -1) ; skip back a keyword + (setq begin (point)) + (cond + ((looking-at "do\\>[^_]") ; iter block is a special case + (if (nth 3 state) (goto-char (nth 3 state)) + (goto-char parse-start) (back-to-indentation)) + (setq indent (ruby-indent-size (current-column) (nth 2 state)))) + (t + (setq indent (+ (current-column) ruby-indent-level))))) + + ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest + (setq indent (ruby-indent-size (current-column) (nth 2 state))))) + (when indent + (goto-char ruby-indent-point) + (end-of-line) + (setq eol (point)) + (beginning-of-line) + (cond + ((and (not (ruby-deep-indent-paren-p paren + (and (cdr (nth 1 state)) + (1- (cdr (nth 1 state)))))) + (re-search-forward ruby-negative eol t)) + (and (not (eq ?_ (char-after (match-end 0)))) + (setq indent (- indent ruby-indent-level)))) + ((and + (save-excursion + (beginning-of-line) + (not (bobp))) + (or (ruby-deep-indent-paren-p t) + (null (car (nth 1 state))))) + ;; goto beginning of non-empty no-comment line + (let (end done) + (while (not done) + (skip-chars-backward " \t\n") + (setq end (point)) + (beginning-of-line) + (if (re-search-forward "^\\s *#" end t) + (beginning-of-line) + (setq done t)))) + (setq bol (point)) + (end-of-line) + ;; skip the comment at the end + (skip-chars-backward " \t") + (let (end (pos (point))) + (beginning-of-line) + (while (and (re-search-forward "#" pos t) + (setq end (1- (point))) + (or (ruby-special-char-p end) + (and (setq state (ruby-parse-region parse-start end)) + (nth 0 state)))) + (setq end nil)) + (goto-char (or end pos)) + (skip-chars-backward " \t") + (setq begin (if (and end (nth 0 state)) pos (cdr (nth 1 state)))) + (setq state (ruby-parse-region parse-start (point)))) + (or (bobp) (forward-char -1)) + (and + (or (and (looking-at ruby-symbol-re) + (skip-chars-backward ruby-symbol-chars) + (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>")) + (not (eq (point) (nth 3 state))) + (save-excursion + (goto-char (match-end 0)) + (not (looking-at "[a-z_]")))) + (and (looking-at ruby-operator-re) + (not (ruby-special-char-p)) + ;; operator at the end of line + (let ((c (char-after (point)))) + (and +;; (or (null begin) +;; (save-excursion +;; (goto-char begin) +;; (skip-chars-forward " \t") +;; (not (or (eolp) (looking-at "#") +;; (and (eq (car (nth 1 state)) ?{) +;; (looking-at "|")))))) + (or (not (eq ?/ c)) + (null (nth 0 (ruby-parse-region (or begin parse-start) (point))))) + (or (not (eq ?| (char-after (point)))) + (save-excursion + (or (eolp) (forward-char -1)) + (cond + ((search-backward "|" nil t) + (skip-chars-backward " \t\n") + (and (not (eolp)) + (progn + (forward-char -1) + (not (looking-at "{"))) + (progn + (forward-word -1) + (not (looking-at "do\\>[^_]"))))) + (t t)))) + (not (eq ?, c)) + (setq op-end t))))) + (setq indent + (cond + ((and + (null op-end) + (not (looking-at (concat "\\<\\(" ruby-block-hanging-re "\\)\\>"))) + (eq (ruby-deep-indent-paren-p t) 'space) + (not (bobp))) + (widen) + (goto-char (or begin parse-start)) + (skip-syntax-forward " ") + (current-column)) + ((car (nth 1 state)) indent) + (t + (+ indent ruby-indent-level)))))))) + (goto-char ruby-indent-point) + (beginning-of-line) + (skip-syntax-forward " ") + (if (looking-at "\\.[^.]") + (+ indent ruby-indent-level) + indent)))) + +(defun ruby-electric-brace (arg) + (interactive "P") + (insert-char last-command-event 1) + (ruby-indent-line t) + (delete-char -1) + (self-insert-command (prefix-numeric-value arg))) + +(eval-when-compile + (defmacro defun-region-command (func args &rest body) + (let ((intr (car body))) + (when (featurep 'xemacs) + (if (stringp intr) (setq intr (cadr body))) + (and (eq (car intr) 'interactive) + (setq intr (cdr intr)) + (setcar intr (concat "_" (car intr))))) + (cons 'defun (cons func (cons args body)))))) + +(defun-region-command ruby-beginning-of-defun (&optional arg) + "Move backward to next beginning-of-defun. +With argument, do this that many times. +Returns t unless search stops due to end of buffer." + (interactive "p") + (and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\_>") + nil 'move (or arg 1)) + (progn (beginning-of-line) t))) + +(defun ruby-beginning-of-indent () + (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\_>") + nil 'move) + (progn + (beginning-of-line) + t))) + +(defun-region-command ruby-end-of-defun (&optional arg) + "Move forward to next end of defun. +An end of a defun is found by moving forward from the beginning of one." + (interactive "p") + (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)") + nil 'move (or arg 1)) + (progn (beginning-of-line) t)) + (forward-line 1)) + +(defun ruby-move-to-block (n) + (let (start pos done down (orig (point))) + (setq start (ruby-calculate-indent)) + (setq down (looking-at (if (< n 0) ruby-block-end-re + (concat "\\<\\(" ruby-block-beg-re "\\)\\>")))) + (while (and (not done) (not (if (< n 0) (bobp) (eobp)))) + (forward-line n) + (cond + ((looking-at "^\\s *$")) + ((looking-at "^\\s *#")) + ((and (> n 0) (looking-at "^=begin\\>")) + (re-search-forward "^=end\\>")) + ((and (< n 0) (looking-at "^=end\\>")) + (re-search-backward "^=begin\\>")) + (t + (setq pos (current-indentation)) + (cond + ((< start pos) + (setq down t)) + ((and down (= pos start)) + (setq done t)) + ((> start pos) + (setq done t))))) + (if done + (save-excursion + (back-to-indentation) + (if (looking-at (concat "\\<\\(" ruby-block-mid-re "\\)\\>")) + (setq done nil))))) + (back-to-indentation) + (when (< n 0) + (let ((eol (point-at-eol)) state next) + (if (< orig eol) (setq eol orig)) + (setq orig (point)) + (while (and (setq next (apply 'ruby-parse-partial eol state)) + (< (point) eol)) + (setq state next)) + (when (cdaadr state) + (goto-char (cdaadr state))) + (backward-word))))) + +(defun-region-command ruby-beginning-of-block (&optional arg) + "Move backward to next beginning-of-block" + (interactive "p") + (ruby-move-to-block (- (or arg 1)))) + +(defun-region-command ruby-end-of-block (&optional arg) + "Move forward to next beginning-of-block" + (interactive "p") + (ruby-move-to-block (or arg 1))) + +(defun-region-command ruby-forward-sexp (&optional cnt) + (interactive "p") + (if (and (numberp cnt) (< cnt 0)) + (ruby-backward-sexp (- cnt)) + (let ((i (or cnt 1))) + (condition-case nil + (while (> i 0) + (skip-syntax-forward " ") + (if (looking-at ",\\s *") (goto-char (match-end 0))) + (cond ((looking-at "\\?\\(\\\\[CM]-\\)*\\\\?\\S ") + (goto-char (match-end 0))) + ((progn + (skip-chars-forward ",.:;|&^~=!?\\+\\-\\*") + (looking-at "\\s(")) + (goto-char (scan-sexps (point) 1))) + ((and (looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>")) + (not (eq (char-before (point)) ?.)) + (not (eq (char-before (point)) ?:))) + (ruby-end-of-block) + (forward-word 1)) + ((looking-at "\\(\\$\\|@@?\\)?\\sw") + (while (progn + (while (progn (forward-word 1) (looking-at "_"))) + (cond ((looking-at "::") (forward-char 2) t) + ((> (skip-chars-forward ".") 0)) + ((looking-at "\\?\\|!\\(=[~=>]\\|[^~=]\\)") + (forward-char 1) nil))))) + ((let (state expr) + (while + (progn + (setq expr (or expr (ruby-expr-beg) + (looking-at "%\\sw?\\Sw\\|[\"'`/]"))) + (nth 1 (setq state (apply 'ruby-parse-partial nil state)))) + (setq expr t) + (skip-chars-forward "<")) + (not expr)))) + (setq i (1- i))) + ((error) (forward-word 1))) + i))) + +(defun-region-command ruby-backward-sexp (&optional cnt) + (interactive "p") + (if (and (numberp cnt) (< cnt 0)) + (ruby-forward-sexp (- cnt)) + (let ((i (or cnt 1))) + (condition-case nil + (while (> i 0) + (skip-chars-backward " \t\n,.:;|&^~=!?\\+\\-\\*") + (forward-char -1) + (cond ((looking-at "\\s)") + (goto-char (scan-sexps (1+ (point)) -1)) + (case (char-before) + (?% (forward-char -1)) + ('(?q ?Q ?w ?W ?r ?x) + (if (eq (char-before (1- (point))) ?%) (forward-char -2)))) + nil) + ((looking-at "\\s\"\\|\\\\\\S_") + (let ((c (char-to-string (char-before (match-end 0))))) + (while (and (search-backward c) + (oddp (skip-chars-backward "\\"))))) + nil) + ((looking-at "\\s.\\|\\s\\") + (if (ruby-special-char-p) (forward-char -1))) + ((looking-at "\\s(") nil) + (t + (forward-char 1) + (while (progn (forward-word -1) + (case (char-before) + (?_ t) + (?. (forward-char -1) t) + ((?$ ?@) + (forward-char -1) + (and (eq (char-before) (char-after)) (forward-char -1))) + (?: + (forward-char -1) + (eq (char-before) :))))) + (if (looking-at ruby-block-end-re) + (ruby-beginning-of-block)) + nil)) + (setq i (1- i))) + ((error))) + i))) + +(defun ruby-reindent-then-newline-and-indent () + (interactive "*") + (newline) + (save-excursion + (end-of-line 0) + (indent-according-to-mode) + (delete-region (point) (progn (skip-chars-backward " \t") (point)))) + (indent-according-to-mode)) + +(fset 'ruby-encomment-region (symbol-function 'comment-region)) + +(defun ruby-decomment-region (beg end) + (interactive "r") + (save-excursion + (goto-char beg) + (while (re-search-forward "^\\([ \t]*\\)#" end t) + (replace-match "\\1" nil nil) + (save-excursion + (ruby-indent-line))))) + +(defun ruby-insert-end () + (interactive) + (insert "end") + (ruby-indent-line t) + (end-of-line)) + +(defun ruby-mark-defun () + "Put mark at end of this Ruby function, point at beginning." + (interactive) + (push-mark (point)) + (ruby-end-of-defun) + (push-mark (point) nil t) + (ruby-beginning-of-defun) + (re-search-backward "^\n" (- (point) 1) t)) + +(defun ruby-indent-exp (&optional shutup-p) + "Indent each line in the balanced expression following point syntactically. +If optional SHUTUP-P is non-nil, no errors are signalled if no +balanced expression is found." + (interactive "*P") + (let ((here (point-marker)) start top column (nest t)) + (set-marker-insertion-type here t) + (unwind-protect + (progn + (beginning-of-line) + (setq start (point) top (current-indentation)) + (while (and (not (eobp)) + (progn + (setq column (ruby-calculate-indent start)) + (cond ((> column top) + (setq nest t)) + ((and (= column top) nest) + (setq nest nil) t)))) + (ruby-indent-to column) + (beginning-of-line 2))) + (goto-char here) + (set-marker here nil)))) + +(defun ruby-add-log-current-method () + "Return current method string." + (condition-case nil + (save-excursion + (let (mname mlist (indent 0)) + ;; get current method (or class/module) + (if (re-search-backward + (concat "^[ \t]*\\(def\\|class\\|module\\)[ \t]+" + "\\(" + ;; \\. and :: for class method + "\\([A-Za-z_]" ruby-symbol-re "*\\|\\.\\|::" "\\)" + "+\\)") + nil t) + (progn + (setq mname (match-string 2)) + (unless (string-equal "def" (match-string 1)) + (setq mlist (list mname) mname nil)) + (goto-char (match-beginning 1)) + (setq indent (current-column)) + (beginning-of-line))) + ;; nest class/module + (while (and (> indent 0) + (re-search-backward + (concat + "^[ \t]*\\(class\\|module\\)[ \t]+" + "\\([A-Z]" ruby-symbol-re "*\\)") + nil t)) + (goto-char (match-beginning 1)) + (if (< (current-column) indent) + (progn + (setq mlist (cons (match-string 2) mlist)) + (setq indent (current-column)) + (beginning-of-line)))) + (when mname + (let ((mn (split-string mname "\\.\\|::"))) + (if (cdr mn) + (progn + (cond + ((string-equal "" (car mn)) + (setq mn (cdr mn) mlist nil)) + ((string-equal "self" (car mn)) + (setq mn (cdr mn))) + ((let ((ml (nreverse mlist))) + (while ml + (if (string-equal (car ml) (car mn)) + (setq mlist (nreverse (cdr ml)) ml nil)) + (or (setq ml (cdr ml)) (nreverse mlist)))))) + (if mlist + (setcdr (last mlist) mn) + (setq mlist mn)) + (setq mn (last mn 2)) + (setq mname (concat "." (cadr mn))) + (setcdr mn nil)) + (setq mname (concat "#" mname))))) + ;; generate string + (if (consp mlist) + (setq mlist (mapconcat (function identity) mlist "::"))) + (if mname + (if mlist (concat mlist mname) mname) + mlist))))) + +(defun ruby-brace-to-do-end () + (when (looking-at "{") + (let ((orig (point)) (end (progn (ruby-forward-sexp) (point))) + oneline (end (make-marker))) + (setq oneline (and (eolp) (<= (point-at-bol) orig))) + (when (eq (char-before) ?\}) + (delete-char -1) + (cond + (oneline + (insert "\n") + (set-marker end (point))) + ((eq (char-syntax (preceding-char)) ?w) + (insert " "))) + (insert "end") + (if (eq (char-syntax (following-char)) ?w) + (insert " ")) + (goto-char orig) + (delete-char 1) + (if (eq (char-syntax (preceding-char)) ?w) + (insert " ")) + (insert "do") + (when (looking-at "\\sw\\||") + (insert " ") + (backward-char)) + (when oneline + (setq orig (point)) + (when (cond + ((looking-at "\\s *|") + (goto-char (match-end 0)) + (and (search-forward "|" (point-at-eol) 'move) + (not (eolp)))) + (t)) + (while (progn + (insert "\n") + (ruby-forward-sexp) + (looking-at "\\s *;\\s *")) + (delete-char (- (match-end 0) (match-beginning 0)))) + (goto-char orig) + (beginning-of-line 2) + (indent-region (point) end)) + (goto-char orig)) + t)))) + +(defun ruby-do-end-to-brace () + (when (and (or (bolp) + (not (memq (char-syntax (preceding-char)) '(?w ?_)))) + (looking-at "\\]\\|\\(^\\|\\s \\)\\(if\\|elsif\\|unless\\|while\\|until\\|when\\|and\\|or\\|&&\\|||\\)\\|g?sub!?\\|scan\\|split!?\\)\\s *\\(/\\)[^/\n\\\\]*\\(\\\\.[^/\n\\\\]*\\)*\\(/\\)" + (4 (7 . ?/)) + (6 (7 . ?/))) + ("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil)) + ("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil)) + (,(concat ruby-here-doc-beg-re ".*\\(\n\\)") + ,(+ 1 (regexp-opt-depth ruby-here-doc-beg-re)) + (ruby-here-doc-beg-syntax)) + (,ruby-here-doc-end-re 3 (ruby-here-doc-end-syntax)))) + + (unless (functionp 'syntax-ppss) + (defun syntax-ppss (&optional pos) + (parse-partial-sexp (point-min) (or pos (point))))) + + (defun ruby-in-ppss-context-p (context &optional ppss) + (let ((ppss (or ppss (syntax-ppss (point))))) + (if (cond + ((eq context 'anything) + (or (nth 3 ppss) + (nth 4 ppss))) + ((eq context 'string) + (nth 3 ppss)) + ((eq context 'heredoc) + (and (nth 3 ppss) + ;; If it's generic string, it's a heredoc and we don't care + ;; See `parse-partial-sexp' + (not (numberp (nth 3 ppss))))) + ((eq context 'non-heredoc) + (and (ruby-in-ppss-context-p 'anything) + (not (ruby-in-ppss-context-p 'heredoc)))) + ((eq context 'comment) + (nth 4 ppss)) + (t + (error (concat + "Internal error on `ruby-in-ppss-context-p': " + "context name `" (symbol-name context) "' is unknown")))) + t))) + + (defun ruby-in-here-doc-p () + (save-excursion + (let ((old-point (point)) (case-fold-search nil)) + (beginning-of-line) + (catch 'found-beg + (while (and (re-search-backward ruby-here-doc-beg-re nil t) + (not (ruby-singleton-class-p))) + (if (not (or (ruby-in-ppss-context-p 'anything) + (ruby-here-doc-find-end old-point))) + (throw 'found-beg t))))))) + + (defun ruby-here-doc-find-end (&optional limit) + "Expects the point to be on a line with one or more heredoc +openers. Returns the buffer position at which all heredocs on the +line are terminated, or nil if they aren't terminated before the +buffer position `limit' or the end of the buffer." + (save-excursion + (beginning-of-line) + (catch 'done + (let ((eol (save-excursion (end-of-line) (point))) + (case-fold-search nil) + ;; Fake match data such that (match-end 0) is at eol + (end-match-data (progn (looking-at ".*$") (match-data))) + beg-match-data end-re) + (while (re-search-forward ruby-here-doc-beg-re eol t) + (setq beg-match-data (match-data)) + (setq end-re (ruby-here-doc-end-match)) + + (set-match-data end-match-data) + (goto-char (match-end 0)) + (unless (re-search-forward end-re limit t) (throw 'done nil)) + (setq end-match-data (match-data)) + + (set-match-data beg-match-data) + (goto-char (match-end 0))) + (set-match-data end-match-data) + (goto-char (match-end 0)) + (point))))) + + (defun ruby-here-doc-beg-syntax () + (save-excursion + (goto-char (match-beginning 0)) + (unless (or (ruby-in-ppss-context-p 'non-heredoc) + (ruby-in-here-doc-p)) + (string-to-syntax "|")))) + + (defun ruby-here-doc-end-syntax () + (let ((pss (syntax-ppss)) (case-fold-search nil)) + (when (ruby-in-ppss-context-p 'heredoc pss) + (save-excursion + (goto-char (nth 8 pss)) ; Go to the beginning of heredoc. + (let ((eol (point))) + (beginning-of-line) + (if (and (re-search-forward (ruby-here-doc-beg-match) eol t) ; If there is a heredoc that matches this line... + (not (ruby-in-ppss-context-p 'anything)) ; And that's not inside a heredoc/string/comment... + (progn (goto-char (match-end 0)) ; And it's the last heredoc on its line... + (not (re-search-forward ruby-here-doc-beg-re eol t)))) + (string-to-syntax "|"))))))) + + (eval-when-compile + (put 'ruby-mode 'font-lock-defaults + '((ruby-font-lock-keywords) + nil nil nil + beginning-of-line + (font-lock-syntactic-keywords + . ruby-font-lock-syntactic-keywords)))) + + (defun ruby-font-lock-docs (limit) + (if (re-search-forward "^=begin\\(\\s \\|$\\)" limit t) + (let (beg) + (beginning-of-line) + (setq beg (point)) + (forward-line 1) + (if (re-search-forward "^=end\\(\\s \\|$\\)" limit t) + (progn + (set-match-data (list beg (point))) + t))))) + + (defun ruby-font-lock-maybe-docs (limit) + (let (beg) + (save-excursion + (if (and (re-search-backward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t) + (string= (match-string 1) "begin")) + (progn + (beginning-of-line) + (setq beg (point))))) + (if (and beg (and (re-search-forward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t) + (string= (match-string 1) "end"))) + (progn + (set-match-data (list beg (point))) + t) + nil))) + + (defvar ruby-font-lock-syntax-table + (let* ((tbl (copy-syntax-table ruby-mode-syntax-table))) + (modify-syntax-entry ?_ "w" tbl) + tbl)) + + (defconst ruby-font-lock-keywords + (list + ;; functions + '("^\\s *def\\s +\\([^( \t\n]+\\)" + 1 font-lock-function-name-face) + ;; keywords + (cons (concat + "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\_<\\(defined\\?\\|" + (regexp-opt + '("alias" + "and" + "begin" + "break" + "case" + "catch" + "class" + "def" + "do" + "elsif" + "else" + "fail" + "ensure" + "for" + "end" + "if" + "in" + "module" + "next" + "not" + "or" + "raise" + "redo" + "rescue" + "retry" + "return" + "then" + "throw" + "super" + "unless" + "undef" + "until" + "when" + "while" + "yield" + ) + t) + "\\)" + ruby-keyword-end-re) + 2) + ;; here-doc beginnings + (list ruby-here-doc-beg-re 0 'font-lock-string-face) + ;; variables + '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\_<\\(nil\\|self\\|true\\|false\\)\\>" + 2 font-lock-variable-name-face) + ;; variables + '("\\(\\$\\([^a-zA-Z0-9 \n]\\|[0-9]\\)\\)\\W" + 1 font-lock-variable-name-face) + '("\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+" + 0 font-lock-variable-name-face) + ;; embedded document + '(ruby-font-lock-docs + 0 font-lock-comment-face t) + '(ruby-font-lock-maybe-docs + 0 font-lock-comment-face t) + ;; general delimited string + '("\\(^\\|[[ \t\n<+(,=]\\)\\(%[xrqQwW]?\\([^<[{(a-zA-Z0-9 \n]\\)[^\n\\\\]*\\(\\\\.[^\n\\\\]*\\)*\\(\\3\\)\\)" + (2 font-lock-string-face)) + ;; constants + '("\\(^\\|[^_]\\)\\_<\\([A-Z]+\\(\\w\\|_\\)*\\)" + 2 font-lock-type-face) + ;; symbols + '("\\(^\\|[^:]\\)\\(:\\([-+~]@?\\|[/%&|^`]\\|\\*\\*?\\|<\\(<\\|=>?\\)?\\|>[>=]?\\|===?\\|=~\\|![~=]?\\|\\[\\]=?\\|\\(\\w\\|_\\)+\\([!?=]\\|\\b_*\\)\\|#{[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\)\\)" + 2 font-lock-reference-face) + '("\\(^\\s *\\|[\[\{\(,]\\s *\\|\\sw\\s +\\)\\(\\(\\sw\\|_\\)+\\):[^:]" 2 font-lock-reference-face) + ;; expression expansion + '("#\\({[^}\n\\\\]*\\(\\\\.[^}\n\\\\]*\\)*}\\|\\(\\$\\|@\\|@@\\)\\(\\w\\|_\\)+\\)" + 0 font-lock-variable-name-face t) + ;; warn lower camel case + ;'("\\<[a-z]+[a-z0-9]*[A-Z][A-Za-z0-9]*\\([!?]?\\|\\>\\)" + ; 0 font-lock-warning-face) + ) + "*Additional expressions to highlight in ruby mode.")) + +(eval-when-hilit19-available + (hilit-set-mode-patterns + 'ruby-mode + '(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string) + ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string) + ("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string) + ("^\\s *#.*$" nil comment) + ("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment) + ("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string) + ("^\\s *\\(require\\|load\\).*$" nil include) + ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl) + ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun) + ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\|yield\\)\\>\\([^_]\\|$\\)" 1 defun) + ("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\|catch\\|throw\\|self\\|nil\\)\\>\\([^_]\\|$\\)" 1 keyword) + ("\\$\\(.\\|\\sw+\\)" nil type) + ("[$@].[a-zA-Z_0-9]*" nil struct) + ("^__END__" nil label)))) + + +;;;###autoload +(defun ruby-mode () + "Major mode for editing ruby scripts. +\\[ruby-indent-command] properly indents subexpressions of multi-line +class, module, def, if, while, for, do, and case statements, taking +nesting into account. + +The variable ruby-indent-level controls the amount of indentation. +\\{ruby-mode-map}" + (interactive) + (kill-all-local-variables) + (use-local-map ruby-mode-map) + (setq mode-name "Ruby") + (setq major-mode 'ruby-mode) + (ruby-mode-variables) + + (make-local-variable 'imenu-create-index-function) + (setq imenu-create-index-function 'ruby-imenu-create-index) + + (make-local-variable 'add-log-current-defun-function) + (setq add-log-current-defun-function 'ruby-add-log-current-method) + + (add-hook + (cond ((boundp 'before-save-hook) + (make-local-variable 'before-save-hook) + 'before-save-hook) + ((boundp 'write-contents-functions) 'write-contents-functions) + ((boundp 'write-contents-hooks) 'write-contents-hooks)) + 'ruby-mode-set-encoding) + + (set (make-local-variable 'font-lock-defaults) '((ruby-font-lock-keywords) nil nil)) + (set (make-local-variable 'font-lock-keywords) ruby-font-lock-keywords) + (set (make-local-variable 'font-lock-syntax-table) ruby-font-lock-syntax-table) + (set (make-local-variable 'font-lock-syntactic-keywords) ruby-font-lock-syntactic-keywords) + + (if (fboundp 'run-mode-hooks) + (run-mode-hooks 'ruby-mode-hook) + (run-hooks 'ruby-mode-hook))) + +(provide 'ruby-mode) diff --git a/vendor/tomorrow-night-paradise-theme b/vendor/tomorrow-night-paradise-theme new file mode 160000 index 0000000..70225a5 --- /dev/null +++ b/vendor/tomorrow-night-paradise-theme @@ -0,0 +1 @@ +Subproject commit 70225a5bf90d495e13a9260bfdc268632ece0801