summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Dominik <carsten.dominik@gmail.com>2011-05-11 09:48:36 +0200
committerCarsten Dominik <carsten.dominik@gmail.com>2011-05-11 10:11:45 +0200
commitbffdfeb7fcd6c094d44e754ace7ce28fab81f2ff (patch)
treebca41e3e3a1ad0dd66041687750a94e809b9a29d
parentf73f0f6323f81b482d93db4c4f71b2841852d021 (diff)
downloadorg-mode-bffdfeb7fcd6c094d44e754ace7ce28fab81f2ff.tar.gz
Implement a minor mode for the editor following the cursor through the table
* doc/org.texi (Built-in table editor): Document the table field follow mode. * lisp/org-table.el (org-table-exit-follow-field-mode-when-leaving-table): New option. (org-table-check-inside-data-field): New optional argument `noerror'. When set, the function will only return nil instead of throwing an error. (org-table-edit-field): Interpret double prefix argument, and improve the properties of the editing window. (org-table-follow-field-mode): New minor mode. (org-table-follow-fields-with-editor): New function. The main purpose of this functionality is to make working with table with long fields simpler, by always showing the full content of the current field. This functionality is based on the following mailing list thread http://thread.gmane.org/gmane.emacs.orgmode/41584 and contains ideas by Jonny, Juan Pechiar, and Michael Brand.
-rw-r--r--doc/org.texi5
-rw-r--r--lisp/org-table.el75
2 files changed, 68 insertions, 12 deletions
diff --git a/doc/org.texi b/doc/org.texi
index 3988838..3567031 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -2064,7 +2064,10 @@ increment. This key is also used by shift-selection and related modes
Edit the current field in a separate window. This is useful for fields that
are not fully visible (@pxref{Column width and alignment}). When called with
a @kbd{C-u} prefix, just make the full field visible, so that it can be
-edited in place.
+edited in place. When called with two @kbd{C-u} prefixes, make the editor
+window follow the cursor through the table and always show the current
+field. The follow mode exits automatically when the cursor leaves the table,
+or when you repeat this command with @kbd{C-u C-u C-c `}.
@c
@item M-x org-table-import
Import a file as a table. The table should be TAB or whitespace
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 58aa835..0f71d57 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -162,6 +162,16 @@ Only relevant when `org-enable-table-editor' is equal to `optimized'."
:group 'org-table-editing
:type 'boolean)
+(defcustom org-table-exit-follow-field-mode-when-leaving-table t
+ "Non-nil means automatically exit the follow mode.
+When nil, the follow mode will stay on and be active in any table
+the cursor enters. Since the table follow filed mode messes with the
+window configuration, it is not recommended to set this variable to nil,
+except maybe locally in a special file that has mostly tables with long
+fields."
+ :group 'org-table
+ :type 'boolean)
+
(defcustom org-table-fix-formulas-confirm nil
"Whether the user should confirm when Org fixes formulas."
:group 'org-table-editing
@@ -1045,7 +1055,7 @@ copying. In the case of a timestamp, increment by one day."
(org-move-to-column col))
(error "No non-empty field found"))))
-(defun org-table-check-inside-data-field ()
+(defun org-table-check-inside-data-field (&optional noerror)
"Is point inside a table data field?
I.e. not on a hline or before the first or after the last column?
This actually throws an error, so it aborts the current command."
@@ -1053,7 +1063,10 @@ This actually throws an error, so it aborts the current command."
(= (org-table-current-column) 0)
(org-at-table-hline-p)
(looking-at "[ \t]*$"))
- (error "Not in table data field")))
+ (if noerror
+ nil
+ (error "Not in table data field"))
+ t))
(defvar org-table-clip nil
"Clipboard for table regions.")
@@ -1776,21 +1789,32 @@ This is mainly useful for fields that contain hidden parts.
When called with a \\[universal-argument] prefix, just make the full field visible so that
it can be edited in place."
(interactive "P")
- (if arg
- (let ((b (save-excursion (skip-chars-backward "^|") (point)))
- (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
- (remove-text-properties b e '(org-cwidth t invisible t
- display t intangible t))
- (if (and (boundp 'font-lock-mode) font-lock-mode)
- (font-lock-fontify-block)))
+ (cond
+ ((equal arg '(16))
+ (org-table-follow-field-mode (if org-table-follow-field-mode -1 1)))
+ (arg
+ (let ((b (save-excursion (skip-chars-backward "^|") (point)))
+ (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
+ (remove-text-properties b e '(org-cwidth t invisible t
+ display t intangible t))
+ (if (and (boundp 'font-lock-mode) font-lock-mode)
+ (font-lock-fontify-block))))
+ (t
(let ((pos (move-marker (make-marker) (point)))
(field (org-table-get-field))
(cw (current-window-configuration))
p)
- (org-switch-to-buffer-other-window "*Org tmp*")
+ (goto-char pos)
+ (org-switch-to-buffer-other-window "*Org Table Edit Field*")
+ (when (and (local-variable-p 'org-field-marker)
+ (markerp org-field-marker))
+ (move-marker org-field-marker nil))
(erase-buffer)
(insert "#\n# Edit field and finish with C-c C-c\n#\n")
(let ((org-inhibit-startup t)) (org-mode))
+ (auto-fill-mode -1)
+ (setq truncate-lines nil)
+ (setq word-wrap t)
(goto-char (setq p (point-max)))
(insert (org-trim field))
(remove-text-properties p (point-max)
@@ -1800,7 +1824,7 @@ it can be edited in place."
(org-set-local 'org-finish-function 'org-table-finish-edit-field)
(org-set-local 'org-window-configuration cw)
(org-set-local 'org-field-marker pos)
- (message "Edit and finish with C-c C-c"))))
+ (message "Edit and finish with C-c C-c")))))
(defun org-table-finish-edit-field ()
"Finish editing a table data field.
@@ -1825,6 +1849,35 @@ the table and kill the editing buffer."
(org-table-align)
(message "New field value inserted")))
+(define-minor-mode org-table-follow-field-mode
+ "Minor mode to make the table field editor window follow the cursor.
+When this mode is active, the field editor window will always show the
+current field. The mode exits automatically when the cursor leaves the
+table (but see `org-table-exit-follow-field-mode-when-leaving-table')."
+ nil " TblFollow" nil
+ (if org-table-follow-field-mode
+ (org-add-hook 'post-command-hook 'org-table-follow-fields-with-editor
+ 'append 'local)
+ (remove-hook 'post-command-hook 'org-table-follow-fields-with-editor 'local)
+ (let* ((buf (get-buffer "*Org Table Edit Field*"))
+ (win (and buf (get-buffer-window buf))))
+ (when win (delete-window win))
+ (when buf
+ (with-current-buffer buf
+ (move-marker org-field-marker nil))
+ (kill-buffer buf)))))
+
+(defun org-table-follow-fields-with-editor ()
+ (if (and org-table-exit-follow-field-mode-when-leaving-table
+ (not (org-at-table-p)))
+ ;; We have left the table, exit the follow mode
+ (org-table-follow-field-mode -1)
+ (when (org-table-check-inside-data-field 'noerror)
+ (let ((win (selected-window)))
+ (org-table-edit-field nil)
+ (org-fit-window-to-buffer)
+ (select-window win)))))
+
(defvar org-timecnt) ; dynamically scoped parameter
(defun org-table-sum (&optional beg end nlast)