emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: John Kitchin <jkitchin@andrew.cmu.edu>
To: Jude DaShiell <jdashiel@panix.com>
Cc: org-mode-email <emacs-orgmode@gnu.org>
Subject: Re: org table integrity
Date: Sun, 2 Feb 2020 20:50:48 -0500	[thread overview]
Message-ID: <CAJ51EToM9fMC1s3Cf6jREoAFvzu+VF-JaAUcUibBqZOigfmXmQ@mail.gmail.com> (raw)
In-Reply-To: <alpine.NEB.2.21.2002012106170.28210@panix1.panix.com>

[-- Attachment #1: Type: text/plain, Size: 3476 bytes --]

This is a little tricky to guarantee; there are just so many ways to edit a

One way to do this is like the following. The idea is to use the
org-cycle-hook to check the last cell you were in when you pressed TAB in a
table. This of course does not work if you don't use tab, and in its
current form does not work on shift-tab.  You set an #+attr_org line to
have list of predicate functions for each column. stringp is tricky, all
the cells are strings, so I tried a regexp for numbers. numberp is also not
quite right, for me "1a" converts to 1. This code is pretty lightly tested,
so tread warily!

I had to add the advice for some reason. I don't know why, but it appears
to me the org-cycle-hook does not get run inside org-cycle. I don't think
this should be necessary, but it was to test this out.

Here is the code. After you run it, each time you tab through the table,
you should see some messages telling you what was tested, and some of them
should cause an error with a message about it.

#+BEGIN_SRC emacs-lisp
(defun org-timestamp-p (contents)
  "Return non-nil if CONTENTS is a legal org timestamp"
    (insert contents)
    (goto-char (point-min))
    (re-search-forward org-element--timestamp-regexp nil t)))

(defun check-table-integrity (_state)
  ;; get previous contents
  (let* ((column)
(element (org-element-context))

    (while (and (org-at-table-p) (not (eq 'table (car element)))
(setq element (org-element-property :parent element))))

    (when (eq 'table (car element))

      (setq attr (car (org-element-property :attr_org element))
   funcs (plist-get (read (format "(%s)" attr)) :types))

(setq column (org-table-current-column)
     func (nth (- column 1) funcs)
     field (org-table-get-field)
     valid (funcall (eval func) (s-trim field)))

(message "checking %s field with %s" field func)

;; this is a little tricky. valid is non-nil, and 0 is considered non-nil
(unless valid
 (error "%s did not pass %s" field func))))))

(add-hook 'org-cycle-hook 'check-table-integrity)

(advice-add 'org-cycle :after (lambda (x) (cl-loop for func in
  do (funcall func ""))))


#+attr_org: :types ('org-timestamp-p (lambda (x) (string-match-p "[0-9]+"
x)) 'stringp)
| [2020-02-02 Sun] |  1 | no  |
| [2020-02-09 Sun] | no | yes |
| not a ts         |  3 | 3   |

An alternative way to do this might be to have a function that runs when
you leave a table, then it could validate the cells in a similar way. The
easy way to do this is with a post-command hook, but this is hard to do
without performance hits. The harder way to do it is with cursor sensor
functions, but this requires a hack on font-lock for tables. A final way is
to make a save/kill-buffer hook function that would map over each table and
validate them before allowing the save/kill to complete.


Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213

On Sat, Feb 1, 2020 at 9:09 PM Jude DaShiell <jdashiel@panix.com> wrote:

> Does a way exist in orgmode to fix a column so that it only stores time
> stamps?  A table I'm using has two columns that could this kind of error
> protection and two that should contain text.
> --

[-- Attachment #2: Type: text/html, Size: 4582 bytes --]

      parent reply	other threads:[~2020-02-03  1:51 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-02  2:09 org table integrity Jude DaShiell
2020-02-02  6:57 ` Bastien
2020-02-03  1:50 ` John Kitchin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAJ51EToM9fMC1s3Cf6jREoAFvzu+VF-JaAUcUibBqZOigfmXmQ@mail.gmail.com \
    --to=jkitchin@andrew.cmu.edu \
    --cc=emacs-orgmode@gnu.org \
    --cc=jdashiel@panix.com \


* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).