[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/captain 3ada93d 01/11: Added captain package
From: |
Stefan Monnier |
Subject: |
[elpa] externals/captain 3ada93d 01/11: Added captain package |
Date: |
Tue, 1 Dec 2020 15:22:46 -0500 (EST) |
branch: externals/captain
commit 3ada93dc1fb5a66afa054833d346023c0fef3f50
Author: Ian Dunn <dunni@gnu.org>
Commit: Ian Dunn <dunni@gnu.org>
Added captain package
Single-file package to handle automatic capitalization
* packages/captain/captain.el: Added.
---
captain.el | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 194 insertions(+)
diff --git a/captain.el b/captain.el
new file mode 100644
index 0000000..8c019e0
--- /dev/null
+++ b/captain.el
@@ -0,0 +1,194 @@
+;;; captain.el --- CAPiTalization is Automatic IN emacs -*- lexical-binding:
t; -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: Ian Dunn <dunni@gnu.org>
+;; Maintainer: Ian Dunn <dunni@gnu.org>
+;; Keywords: editing
+;; Version: 1.0
+
+;; This file is part of GNU 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 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The captain handles capitalizing text as you type, freeing you to do other
+;; things.
+
+;; Invoke the captain across the globe with `global-captain-mode', or just on
+;; one ship (buffer) at a time with `captain-mode'.
+
+;; For normal people:
+
+;; Automatically capitalizes the first word of a sentence as you type. The
+;; bounds of a sentence are determined by local variable
+;; `captain-sentence-start-function'. For example, you can set it to find the
+;; start of a list or heading in `org-mode'.
+
+;; Further control can be obtained by modifying the local variable
+;; `captain-predicate', which tells the captain when to work and when to relax.
+
+;; It's also possible to automatically capitalize individual words using the
+;; command `captain-capitalize-word'. This will capitalize the word at point
+;; and tell the captain about it, so he knows that you want it capitalized from
+;; then on.
+
+;; This solves a similar problem to that of Kevin Rodgers's auto-capitalize
+;; package, but using more modern Emacs features.
+
+;;; Code:
+
+(eval-when-compile (require 'subr-x))
+(require 'thingatpt)
+
+(defvar-local captain-predicate nil
+ "Predicate to check for whether auto-capitalization should be handled.
+
+Should be a function of no arguments, and return non-nil if
+auto-capitalization should be performed at the current point.
+
+For example, this could be a function to check if point is in a
+comment.")
+
+(defun captain-should-capitalize-p ()
+ "Return non-nil if the captain should auto-capitalize your work."
+ (when captain-predicate
+ (funcall captain-predicate)))
+
+(defun captain--default-sentence-start ()
+ "Default value of `captain-sentence-start-function'.
+
+Just runs `bounds-of-thing-at-point' for a sentence."
+ (car (bounds-of-thing-at-point 'sentence)))
+
+(defvar-local captain-sentence-start-function
+ #'captain--default-sentence-start
+ "Function to determine the start of the current sentence.
+
+This should be a function of no arguments that returns the point
+at which the current function begins.")
+
+(defun captain--run ()
+ "Automatically capitalize the word preceding point if it is the start of a
sentence."
+ ;; Only do this if the last inserted character isn't part of a word,
+ ;; (preceding-char) is the previously inserted character;
+ ;; We also need the character before that (It must be a word constituent, so
+ ;; enter or space don't keep trying to capitalize the sentence).
+ (when (and (captain-should-capitalize-p)
+ (not (or (bobp) (eq (char-syntax (preceding-char)) ?w)))
+ (eq (char-syntax (save-excursion (forward-char -1)
+ (preceding-char)))
+ ?w))
+ (save-excursion
+ ;; Move back to the word that was just finished, and determine if it
+ ;; starts a sentence.
+ (backward-word-strictly)
+ ;; Ensure we're still expected to capitalize. Case: New character put us
+ ;; inside a string, but backward-word-strictly brought us outside the
+ ;; string.
+ (when (captain-should-capitalize-p)
+ (when-let ((word-bounds (bounds-of-thing-at-point 'word))
+ (sentence-start (funcall captain-sentence-start-function)))
+ (cond
+ ((let ((case-fold-search nil))
+ (string-match-p "[[:upper:]]" (word-at-point)))
+ nil)
+ ;; This word does start a sentence, so capitalize it
+ ((eq (car word-bounds) sentence-start) (capitalize-word 1))
+ ;; Word bound will only ever be one greater than the sentence bound
if
+ ;; the sentence begins with some sort of punctuation. Remember,
spaces
+ ;; don’t count, so if we have a sentence starting with "A ball...",
+ ;; ’ball’ wont trigger this, only ’A’.
+ ((eq (car word-bounds) (1+ sentence-start))
+ (capitalize-word 1))))))))
+
+(defun captain-capitalize-sentence ()
+ "Tell the captain to capitalize the start of the current sentence."
+ (interactive)
+ (save-excursion
+ (goto-char (funcall captain-sentence-start-function))
+ (capitalize-word 1)))
+
+;;;###autoload
+(define-minor-mode captain-mode
+ "Call the captain to automatically capitalize the start of every sentence.
+
+The captain will also automatically capitalize words you've told
+him you want capitalized with `captain-capitalize-word'.
+
+\\{captain-mode-map}"
+ :init-value nil
+ :lighter " Captain"
+ :global nil
+ (if captain-mode
+ (progn
+ (add-hook 'post-self-insert-hook 'captain--run nil t))
+ (remove-hook 'post-self-insert-hook 'captain--run t)))
+
+;;;###autoload
+(define-globalized-minor-mode global-captain-mode
+ captain-mode captain-mode)
+
+;; Support for capitalizing individual words automatically
+
+(define-abbrev-table 'captain-mode-abbrev-table nil
+ "Abbrev table where words that should be automatically capitalized are
stored."
+ :enable-function #'captain-should-capitalize-p)
+
+;; Only enable the abbrev table when captain-mode is active
+(add-to-list 'abbrev-minor-mode-table-alist
+ `(captain-mode ,captain-mode-abbrev-table)
+ 'append
+ #'equal)
+
+(defun captain--start-of-word-p ()
+ "Return non-nil if at the start of a word."
+ (and
+ ;; looking at a word constituent...
+ (eq (char-syntax (following-char)) ?w)
+ ;; ...but before us isn't a word constituent
+ (not (eq (char-syntax (preceding-char)) ?w))))
+
+(defun captain-capitalize-word ()
+ "Tell the captain to capitalize the word at point.
+
+After that, the captain will remember your choice, and
+automatically capitalize the word from then on.
+
+If not looking at a word, move forward to find the next word."
+ (interactive)
+ (save-excursion
+ ;; Cases for where we are:
+ (cond
+ ;; Looking at the start of a word, so don't move
+ ((captain--start-of-word-p))
+ ((word-at-point)
+ ;; If we're in the middle of a word, then move back to the start.
+ (backward-word-strictly))
+ (t
+ ;; Otherwise, we're not on a word, so move forward to find the next one.
+ ;; This is to remain consistent with the behavior of `capitalize-word'.
+ (forward-to-word 1)))
+ (when-let ((old-word (substring-no-properties (word-at-point)))
+ (new-word (capitalize old-word)))
+ ;; Store the abbrev so this word is automatically capitalized later.
+ (define-abbrev captain-mode-abbrev-table
+ old-word new-word nil :count 1))
+ ;; Finally, capitalize the word at point.
+ (capitalize-word 1)))
+
+(provide 'captain)
+
+;;; captain.el ends here
- [elpa] branch externals/captain created (now 574439a), Stefan Monnier, 2020/12/01
- [elpa] externals/captain 3ada93d 01/11: Added captain package,
Stefan Monnier <=
- [elpa] externals/captain 949b6ad 02/11: captain.el: Changed default predicate to enable capitalization, Stefan Monnier, 2020/12/01
- [elpa] externals/captain 66584d2 04/11: captain: Change default predicate to a function, and call it unconditionally, Stefan Monnier, 2020/12/01
- [elpa] externals/captain 072c330 05/11: captain: Change abbrev table to be case sensitive, Stefan Monnier, 2020/12/01
- [elpa] externals/captain 574439a 11/11: * .gitignore: New file, Stefan Monnier, 2020/12/01
- [elpa] externals/captain 956e040 08/11: captain: Added examples for setting captain-predicate to commentary, Stefan Monnier, 2020/12/01
- [elpa] externals/captain db93857 10/11: Updated copyright on auto-correct, captain, and vigenere, Stefan Monnier, 2020/12/01
- [elpa] externals/captain 49c3e29 03/11: captain.el: Reverted last commit, Stefan Monnier, 2020/12/01
- [elpa] externals/captain a341d4c 09/11: captain: Bumped version to 1.0.3, Stefan Monnier, 2020/12/01
- [elpa] externals/captain 2cb4569 07/11: captain: Bumped version, Stefan Monnier, 2020/12/01
- [elpa] externals/captain e167b64 06/11: captain: Fix docstring of captain-predicate to reflect recent change, Stefan Monnier, 2020/12/01