From 58cbd2ca1075fdfe5a7f38842e4ac7dc27bae989 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Tue, 18 Jul 2017 19:38:25 +0200 Subject: [PATCH] renamed --- autoscratch-mode.el | 291 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 autoscratch-mode.el diff --git a/autoscratch-mode.el b/autoscratch-mode.el new file mode 100644 index 0000000..16dbd20 --- /dev/null +++ b/autoscratch-mode.el @@ -0,0 +1,291 @@ +;;; autoscratch-mode.el --- automatically switch scratch buffer mode + +;; Copyright (C) 2017, T.v.Dein + +;; This file is NOT part of Emacs. + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of the +;; License, or (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +;; USA + +;; Version: 0.01 +;; Author: T.v.Dein +;; Keywords: files +;; URL: https://github.com/tlinden/autoscratch +;; License: GNU General Public License >= 2 + +;;; Commentary: +;;;; Introduction: +;; This simple major mode can be used as the initial major mode for +;; the scratch buffer. It automatically switches to another major mode +;; based on regexes triggered by text input. +;; +;; In the default configuration it responds to the first +;; non-whitespace character entered into the scratch buffer and +;; switches major mode based on this. See the variable +;; `autoscratch-triggers-alist' for the defaults. For example, if you +;; enter a paren, it will switch to `emacs-lisp-mode'. + +;;;; Configuration: +;; +;; The minimum configuration looks like this: +;; +;; (require 'autoscratch-mode) +;; (setq initial-major-mode 'autoscratch-mode) +;; (setq initial-scratch-message "") +;; (setq inhibit-startup-screen t) +;; +;; You may, however, configure the trigger list +;; `autoscratch-triggers-alist' according to your preferences. This +;; list consists of cons cells, where the `car' is a regexp and the +;; `cdr' an emacs lisp form (e.g. a lambda or defun). If you want to +;; use regexps which match more than one character, then you need to +;; set `autoscratch-trigger-on-first-char' to `nil' and possibly tune +;; `autoscratch-trigger-after' accordingly. + +;; If no regexp matches and/or `autoscratch-trigger-after' is +;; exceeded, then the `autoscratch-default-trigger' form will be +;; executed, which by default is `fundamental-mode', but you can of +;; course change this. + +;; Autoscratch can also be configured to rename the current buffer +;; after it switched mode based on a trigger and create a new +;; `autoscratch-buffer' in the background. In order to enable this +;; feature, set `autoscratch-fork-after-trigger' to t. + +;; To further tune the trigger bahavior you can tune +;; `autoscratch-trigger-hook' which will be called after executing the +;; form of the matching trigger. + +;;; Code: +;;;; Customizables + +(defgroup autoscratch nil + "Autoscratch Mode." + :prefix "autoscratch-" + :group 'emacs) + +(defcustom autoscratch-triggers-alist + '(("[(;]" . (emacs-lisp-mode)) + ("#" . (autoscratch-select + '(("perl" . (cperl-mode)) + ("ruby" . (ruby-mode)) + ("python" . (python-mode)) + ("conf" . (conf-unix-mode)) + ("shell" . (shell-script-mode))))) + ("[-a-zA-Z0-9]" . (text-mode)) + ("/" . (c-mode)) + ("*" . (progn (insert " ") (org-mode))) + ("." . (fundamental-mode))) + "Default trigger alist for autoscratch mode. + +This list triggers after the first character entered. +You can customize this variable directly or use `add-to-list' +to add more triggers. + +In case there are more possibilities for a character, you can +use `autoscratch-select' to make autoscratch ask interactively +for a major mode to switch to, which see. A good example for +such a character is # which is the comment-char in many modes." + :group 'autoscratch + :type 'list) + +(defcustom autoscratch-trigger-on-first-char t + "Trigger after the first character has been entered, no matter what." + :group 'autoscratch + :type 'boolean) + +(defcustom autoscratch-default-trigger '(fundamental-mode) + "Default form to execute when nothing else matches." + :group 'autoscratch + :type 'code) + +(defcustom autoscratch-fork-after-trigger t + "Create a new autoscratch buffer after the trigger fired.") + +(defcustom autoscratch-trigger-after 5 + "Max chars to be entered to force trigger the default form.") + +;;;; Public Vars + +(defvar autoscratch-trigger-hook () + "Hooks called after executing a matching trigger form") + +(defvar autoscratch-rename-hook () + "Hooks called after renaming the current buffer.") + +;;;; Public Functions + +(defun autoscratch-buffer-rename () + "Rename current autoscratch buffer. + +New name is '*autoscratch-* + +Executes `autoscratch-rename-hook' afterwards." + (interactive) + (rename-buffer + (generate-new-buffer-name + (format "*%s-scratch*" + (replace-regexp-in-string + "-mode" "" + (format "%s" major-mode)))) + (run-hooks 'autoscratch-rename-hook))) + +(defun autoscratch-buffer () + "Create and switch to a new autoscratch buffer." + (interactive) + (let ((buf (get-buffer-create "*scratch*"))) + (switch-to-buffer buf) + (autoscratch-mode))) + +(defun autoscratch-select(modelist) + "Interactively ask for major mode to switch to. + +Argument MODELIST must be an alist where the car of each +pair must be a name and the cdr some arbitrary emacs lisp +form. + +Example for MODELIST: + +'((\"perl\" . (cperl-mode)) + (\"ruby\" . (ruby-mode)) + (\"python\" . (python-mode)) + (\"shell\" . (shell-script-mode)) + +This function shall only be called from `autoscratch-triggers-alist'." + (interactive) + (let ((keys ())) + (dolist (e modelist) + (push (car e) keys)) + (eval (cdr (assoc (completing-read "switch mode to: " keys) modelist))))) + + +;;;; Internal Functions + +(defun autoscratch--function-p (form) + "Check if FORM is a function." + (if (symbolp form) + (fboundp form) + (functionp form))) + +(defun autoscratch--fork-and-rename-current () + "Rename buffer and create new autoscratch. +If `autoscratch-fork-after-trigger' is t, create a +new autoscratch buffer and rename the current one +to $mode-scratch." + (interactive) + (let ((cur (current-buffer))) + (when (eq t autoscratch-fork-after-trigger) + (autoscratch-buffer-rename) + (autoscratch-buffer) + (switch-to-buffer cur)))) + +(defun autoscratch--eval-trigger (form) + "If FORM is a function execute interactively, otherwise evaluate it. +Executes `autoscratch-trigger-hook' after evaluation." + (if (autoscratch--function-p form) + (funcall-interactively form) + (eval form)) + (run-hooks 'autoscratch-post-trigger-hook) + (message (format "autoscratch switched to %s" major-mode))) + +(defun autoscratch--look-for-triggers (forward) + (let ((matchform nil)) + (when (or (catch 'done + (dolist (trigger autoscratch-triggers-alist) + (when (if forward + (looking-at (car trigger)) + (looking-back (car trigger))) + (setq matchform (cdr trigger)) + (throw 'done t)))) + (eq t autoscratch-trigger-on-first-char)) + (autoscratch--eval-trigger (or matchform autoscratch-default-trigger)) + (autoscratch--fork-and-rename-current) + ;; else: multichar allowed, continue until max + (when (> (point) autoscratch-trigger-after) + (autoscratch--eval-trigger autoscratch-default-trigger))))) + +(defun autoscratch--self-insert-command (N) + "Look for autoscratch trigger, execute if found and call `self-insert-command'." + (interactive "p") + (self-insert-command N) + (autoscratch--look-for-triggers nil)) + +(defun autoscratch--yank (&optional arg) + "Look for autoscratch trigger, execute if found and call `yank'." + (interactive "*P") + (let ((start (point)) + (end)) + (yank arg) + (setq end (point)) + (goto-char start) + (autoscratch--look-for-triggers t) + (goto-char end))) + +;;;; Keymap + +;;;###autoload +(defvar autoscratch-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [remap self-insert-command] 'autoscratch--self-insert-command) + (define-key map [remap yank] 'autoscratch--yank) + map) + "keymap used by autoscratch mode.") + +;;;; Major Mode + +;;;###autoload +(define-derived-mode autoscratch-mode fundamental-mode "autoscratch" + "Autoscratch major mode automatically switches major mode. + +This simple major mode can be used as the initial major mode for +the scratch buffer. It automatically switches to another major +mode based on regexes triggered by text input. + +In the default configuration it responds to the first +non-whitespace character entered into the scratch buffer and +switches major mode based on this. See the variable +`autoscratch-triggers-alist' for the defaults. For example, if +you enter a paren, it will switch to `emacs-lisp-mode'. + +Configuration: + +The minimum configuration looks like this: + + (require 'autoscratch-mode) + (setq initial-major-mode 'autoscratch-mode) + +You may, however, configure the trigger list +`autoscratch-triggers-alist' according to your preferences. This +list consists of cons cells, where the `car' is a regexp and the +`cdr' an emacs lisp form (e.g. a lambda or defun). If you want +to use regexps which match more than one character, then you need +to set `autoscratch-trigger-on-first-char' to true and possibly +tune `autoscratch-trigger-after' accordingly. + +If no regexp matches and/or `autoscratch-trigger-after' is +exceeded, then the `autoscratch-default-trigger' form will be +executed, which by default is `fundamental-mode', but you can of +course change this. + +Autoscratch can also be configured to rename the current buffer +after it switched mode based on a trigger and create a new +`autoscratch-buffer' in the background. In order to enable this +feature, set `autoscratch-fork-after-trigger' to t. + +\\{autoscratch-mode-map}") + +(provide 'autoscratch-mode) + +;;; autoscratch-mode.el ends here