summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.org57
-rw-r--r--doc/changelog.org19
-rw-r--r--doc/keythemes.org21
-rw-r--r--evil-org.el187
4 files changed, 182 insertions, 102 deletions
diff --git a/README.org b/README.org
index 1c4999d..4d70e42 100644
--- a/README.org
+++ b/README.org
@@ -18,24 +18,49 @@ See [[file:doc/changelog.org][changelog]] for a history of changes.
** Keybindings
- |----------------+---------------------------|
- | key | explanation |
- |----------------+---------------------------|
- | M-ret | insert heading |
- | TAB | fold / unfold headings |
- | gh, gj, gk, gl | navigate between elements |
- | vae | select an element |
- | var | select a subtree |
- | M-h or << | promote a heading |
- | M-l or >> | demote a heading |
- | M-k | move subtree up |
- | M-j | move subtree down |
- | M-S-h or <ar | promote a subtree |
- | M-S-l or >ar | demote a subtree |
- |----------------+---------------------------|
-
[[file:doc/keythemes.org][Full overview of bindings and configuration]]
+*** Quick overview
+
+ |----------------+---------------------------|
+ | key | explanation |
+ |----------------+---------------------------|
+ | gh, gj, gk, gl | navigate between elements |
+ | vae | select an element |
+ |----------------+---------------------------|
+
+**** Headings and items
+
+ |--------------+------------------------|
+ | key | explanation |
+ |--------------+------------------------|
+ | M-ret | insert heading |
+ | TAB | fold / unfold headings |
+ | M-h or << | promote a heading |
+ | M-l or >> | demote a heading |
+ | M-k | move subtree up |
+ | M-j | move subtree down |
+ | M-S-h or <aR | promote a subtree |
+ | M-S-l or >aR | demote a subtree |
+ | vaR | select a subtree |
+ |--------------+------------------------|
+
+**** Tables
+
+ |-----------+--------------------------------|
+ | key | explanation |
+ |-----------+--------------------------------|
+ | ( | previous table cell |
+ | ) | next table cell |
+ | { | beginning of table |
+ | } | end of table |
+ | M-h / M-l | move table column left / right |
+ | M-k / M-j | move table column up / down |
+ | vae | select table cell |
+ | vaE | select table row |
+ | var | select whole table |
+ |-----------+--------------------------------|
+
** Requirements
- org-mode, git://orgmode.org/org-mode.git
diff --git a/doc/changelog.org b/doc/changelog.org
index 37f56a7..bf6fd6d 100644
--- a/doc/changelog.org
+++ b/doc/changelog.org
@@ -1,18 +1,25 @@
-* Version 0.7.0
- - A hook is no longer created automatically
+* Version 0.7.*
+ - A hook is no longer created automatically. The following line of code is from now on required in a user config:
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook 'evil-org-mode) ;; only load with org-mode
#+END_SRC
- This line is from now on required in a user config.
-
- Leader key bindings are removed. See [[file:example_config.el][example config]] for an example how you can set them up yourself.
+ - Redone text objects
+ - Sentence (is/as) and paragraph (ip/ap) text objects no longer get special treatment in tables. Use ie/ae for cells and ir/ar for tables instead.
+ - Move element text object bindings from ie/ae to iE/aE
+ - New text object ie/ae that works on elements and a few smaller objects.
+ - Move subtree text object bindings from ir/ar to iR/aR
+ - New text object ir/ar that works on recursive objects. Repeatable in visual mode.
* Between versions 0.1.2 and 0.6.3
- less controversial default keybindings (see issue [[https://github.com/edwtjo/evil-org-mode/issues/13][#13]])
t, T, O and leader bindings are no longer bound by default, but can be enabled using key themes.
- leader keys are deprecated and evil-leader is no longer required
- customizable movement keys (as a courtesy to dvorak users)
- - operators (>, <) for promotion, demotion. Can also be used for plain indentation when in a code block
- - text objects (ae, ar, ap, as)
+ - new operators (>, <) for promotion, demotion. Can also be used for plain indentation when in a code block.
+ That means < and > are no longer bound to org-meta-left/right.
+ - new text objects
+ - ae, ar to match element, subheading
+ - ap, as to match whole table, table cell in table context
- optional insert mode bindings C-d and C-t
- table support for keys: x, X, (, ), { and }.
diff --git a/doc/keythemes.org b/doc/keythemes.org
index 6519343..9a5241e 100644
--- a/doc/keythemes.org
+++ b/doc/keythemes.org
@@ -66,17 +66,18 @@
|-----+----------------------+-------------------|
** Text objects
- "var" to select an element
+ "vae" to select an element
"dar" to delete a subtree
- "2yar" to yank the parent of a subtree
-
- |-----+-------------+------------------------------------------------|
- | key | function | explanation |
- |-----+-------------+------------------------------------------------|
- | ae | org-element | An org element |
- | ar | org-subtree | A subtree. Use a count to select parent trees. |
- |-----+-------------+------------------------------------------------|
-
+ "2yaR" to yank the parent of a subtree
+
+ |---------+---------------------+-------------------------------------------------|
+ | key | function | explanation |
+ |---------+---------------------+-------------------------------------------------|
+ | ae / ie | org-object | An / inner object (markup, table cell) |
+ | aE / iE | org-element | An / inner element (code block, table row) |
+ | ar / ir | org-greater-element | An / inner recursive element (item list, table) |
+ | aR / iR | org-subtree | An / inner subtree starting with a * |
+ |---------+---------------------+-------------------------------------------------|
** Additional
If you don't want to use hjkl, you can customize evil-org-movement-bindings.
diff --git a/evil-org.el b/evil-org.el
index f9952c8..77251bd 100644
--- a/evil-org.el
+++ b/evil-org.el
@@ -7,7 +7,7 @@
;; Git-Repository: git://github.com/Somelauw/evil-org-mode.git
;; Created: 2012-06-14
;; Forked-since: 2017-02-12
-;; Version: 0.7.1
+;; Version: 0.7.2
;; Package-Requires: ((emacs "24.4") (evil "1.0") (org "8.0.0"))
;; Keywords: evil vim-emulation org-mode key-bindings presets
@@ -365,73 +365,123 @@ If a prefix argument is given, links are opened in incognito mode."
(evil-org-generic-open-links beg end t))
;;; text-objects
-(evil-define-text-object org-element-textobj (count &optional beg end type)
- "An org element."
- (let ((element (org-element-at-point)))
- (list (org-element-property :begin element)
+(defun evil-org-select-an-element (element)
+ "Select an org ELEMENT."
+ (list (org-element-property :begin element)
+ (org-element-property :end element)))
+
+(defun evil-org-select-inner-element (element)
+ "Select inner org ELEMENT."
+ (list (or (org-element-property :contents-begin element)
+ (org-element-property :begin element))
+ (or (org-element-property :contents-end element)
+ ;; Prune post-blank lines from :end element
+ (save-excursion
+ (goto-char (org-element-property :end element))
+ (let ((post-blank (org-element-property :post-blank element)))
+ (unless (zerop post-blank)
+ (forward-line (- post-blank))))
+ (point)))))
+
+(defun evil-org-parent (element)
+ "Find a parent or nearest heading of ELEMENT."
+ (or (org-element-property :parent element)
+ (save-excursion
+ (goto-char (org-element-property :begin element))
+ (if (org-with-limited-levels (org-at-heading-p))
+ (org-up-heading-safe)
+ (org-with-limited-levels (org-back-to-heading)))
+ (org-element-at-point))))
+
+(evil-define-text-object evil-org-an-object (count beg end type)
+ "An org object.
+Matches urls and table cells."
+ (when (null end) (setq end (point)))
+ (when (null beg) (setq beg (point)))
+ (let* ((first (org-element-context))
+ (element first))
+ ;; select next object on repetitive presses
+ (goto-char end)
+ (when (<= (org-element-property :end element) end)
+ (setq element (org-element-context)))
+ (dotimes (_ (1- count))
+ (goto-char (org-element-property :end element))
+ (setq element (org-element-context)))
+ (list (min beg (org-element-property :begin first))
+ (org-element-property :end element))))
+
+(evil-define-text-object evil-org-inner-object (count &optional beg end type)
+ "Select an org object.
+Matches urls and table cells."
+ (evil-org-select-inner-element (org-element-context)))
+
+(evil-define-text-object evil-org-an-element (count &optional beg end type)
+ "An org element.
+Includes paragraphs, table rows and code blocks.
+"
+ (let* ((first (org-element-at-point))
+ (element first))
+ (when (and end (>= end (org-element-property :end element)))
+ (org-forward-element)
+ (setq element (org-element-at-point)))
+ (dotimes (_ (1- count))
+ (org-forward-element)
+ (setq element (org-element-at-point)))
+ (list (min (or beg (point)) (org-element-property :begin first))
(org-element-property :end element))))
-(evil-define-text-object org-subtree-textobj (count &optional beg end type)
+(evil-define-text-object evil-org-inner-element (count &optional beg end type)
+ "Inner org element.
+Includes paragraphs, table rows and code blocks.
+"
+ (evil-org-select-inner-element (org-element-at-point)))
+
+(evil-define-text-object evil-org-a-greater-element (count &optional beg end type)
+ "A greater (recursive) org element.
+Includes tables, list items and subtrees."
+ (when (null count) (setq count 1))
+ (save-excursion
+ (when beg (goto-char beg))
+ (let ((element (org-element-at-point)))
+ (when (or (not (memq (first element) org-element-greater-elements))
+ (and end (>= end (org-element-property :end element))))
+ (setq element (evil-org-parent element)))
+ (dotimes (_ (1- count))
+ (setq element (evil-org-parent element)))
+ (evil-org-select-an-element element))))
+
+(evil-define-text-object evil-org-inner-greater-element (count &optional beg end type)
+ "Inner greater (recursive) org element.
+Includes tables, list items and subtrees."
+ (when (null count) (setq count 1))
+ (save-excursion
+ (when beg (goto-char beg))
+ (let ((element (org-element-at-point)))
+ (unless (memq (first element) org-element-greater-elements)
+ (setq element (evil-org-parent element)))
+ (dotimes (_ (1- count))
+ (setq element (evil-org-parent element)))
+ (evil-org-select-inner-element element))))
+
+(evil-define-text-object evil-org-a-subtree (count &optional beg end type)
"An org subtree."
+ (when (null count) (setq count 1))
(org-with-limited-levels
(cond ((org-at-heading-p) (beginning-of-line))
((org-before-first-heading-p) (user-error "Not in a subtree"))
(t (outline-previous-visible-heading 1))))
(when count (while (and (> count 1) (org-up-heading-safe)) (cl-decf count)))
- (let ((element (org-element-at-point)))
- (list (org-element-property :begin element)
- (org-element-property :end element))))
-
-(evil-define-text-object evil-org-table-inner-cell (count &optional beg end type)
- "Inner org table cell."
- (save-excursion
- (when (not (looking-back "|\\s-?")) (org-table-beginning-of-field 1))
- (let* ((b (point))
- (e (progn (when (looking-at "\\s-*|") ; empty cells
- (right-char)
- (setq count (1- count)))
- (when (> count 0) (org-table-end-of-field count))
- (point))))
- (list b e))))
-
-(evil-define-text-object evil-org-table-a-cell (count &optional beg end type)
- "An org table cell."
- (save-excursion
- (when (not (looking-back "|\\s-?")) (org-table-beginning-of-field 1))
- (list (point)
- (dotimes (_ count (point))
- (org-table-next-field)))))
-
-(evil-define-text-object evil-org-inner-sentence (count &optional beg end type)
- "Inner sentence or table cell when in an org table."
- (if (org-at-table-p)
- (evil-org-table-inner-cell count beg end type)
- (evil-a-sentence count beg end type)))
-
-(evil-define-text-object evil-org-a-sentence (count &optional beg end type)
- "Outer sentence or table cell when in an org table."
- (if (org-at-table-p)
- (evil-org-table-a-cell)
- (evil-a-sentence count beg end type)))
-
-(evil-define-text-object evil-org-inner-paragraph (count &optional beg end type)
- "Inner paragraph or table when in an org table."
- :type line
- (if (org-at-table-p)
- (list (org-table-begin) (org-table-end))
- (evil-select-inner-object 'evil-paragraph beg end type count t)))
-
-(evil-define-text-object evil-org-a-paragraph (count &optional beg end type)
- "A paragraph or table when in an org table."
- :type line
- (if (org-at-table-p)
- (let ((p (point))
- (b (org-table-begin))
- (e (org-table-end)))
- (list (min (or beg p) b)
- (max (or end p) e)))
- (evil-select-an-object 'evil-paragraph beg end type count t)))
+ (evil-org-select-an-element (org-element-at-point)))
+(evil-define-text-object evil-org-inner-subtree (count &optional beg end type)
+ "Inner org subtree."
+ (when (null count) (setq count 1))
+ (org-with-limited-levels
+ (cond ((org-at-heading-p) (beginning-of-line))
+ ((org-before-first-heading-p) (user-error "Not in a subtree"))
+ (t (outline-previous-visible-heading 1))))
+ (when count (while (and (> count 1) (org-up-heading-safe)) (cl-decf count)))
+ (evil-org-select-inner-element (org-element-at-point)))
;;; Keythemes
(defun evil-org--populate-base-bindings ()
"Bindings that are always available."
@@ -467,12 +517,14 @@ If a prefix argument is given, links are opened in incognito mode."
(defun evil-org--populate-textobjects-bindings ()
"Text objects."
(dolist (state '(visual operator))
- (evil-define-key state evil-org-mode-map "ae" 'org-element-textobj)
- (evil-define-key state evil-org-mode-map "ar" 'org-subtree-textobj)
- (evil-define-key state evil-org-mode-map "is" 'evil-org-inner-sentence)
- (evil-define-key state evil-org-mode-map "as" 'evil-org-a-sentence)
- (evil-define-key state evil-org-mode-map "ip" 'evil-org-inner-paragraph)
- (evil-define-key state evil-org-mode-map "ap" 'evil-org-a-paragraph)))
+ (evil-define-key state evil-org-mode-map "ae" 'evil-org-an-object)
+ (evil-define-key state evil-org-mode-map "ie" 'evil-org-inner-object)
+ (evil-define-key state evil-org-mode-map "aE" 'evil-org-an-element)
+ (evil-define-key state evil-org-mode-map "iE" 'evil-org-inner-element)
+ (evil-define-key state evil-org-mode-map "ir" 'evil-org-inner-greater-element)
+ (evil-define-key state evil-org-mode-map "ar" 'evil-org-a-greater-element)
+ (evil-define-key state evil-org-mode-map "aR" 'evil-org-a-subtree)
+ (evil-define-key state evil-org-mode-map "iR" 'evil-org-inner-subtree)))
(defun evil-org--populate-insert-bindings ()
"Define insert mode bindings."
@@ -525,11 +577,6 @@ If a prefix argument is given, links are opened in incognito mode."
(kbd (concat "C-S-" .up)) 'org-shiftcontrolup
(kbd (concat "C-S-" .down)) 'org-shiftcontroldown))))
-;; (let ((state (if evil-org-use-additional-insert '(normal insert) 'normal)))
-;; (evil-define-key state evil-org-mode-map
-;; (kbd "M-o") 'evil-org-insert-subheading
-;; (kbd "M-t") 'evil-org-insert-subtodo))
-
(defun evil-org--populate-shift-bindings ()
"Shift bindings that conflict with evil bindings."
(let-alist evil-org-movement-bindings