* [RFC] Org linting library
@ 2015-04-19 13:31 Nicolas Goaziou
2015-04-19 14:23 ` Rasmus
` (7 more replies)
0 siblings, 8 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-04-19 13:31 UTC (permalink / raw)
To: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 2677 bytes --]
Hello,
The following library implements linting for Org syntax. The sole public
function is `org-lint', which see.
Internally, the library defines a new structure: `org-lint-checker',
with the following slots:
- NAME: Unique check identifier, as a symbol. The check is done
calling the function `org-lint-NAME' with one mandatory argument,
the parse tree describing the current Org buffer. Such function
calls are wrapped within a `save-excursion' and point is always at
`point-min'. Its return value has to be an alist (POSITION MESSAGE)
when POSITION refer to the buffer position of the error, as an
integer, and MESSAGE is a strings describing the error.
- DESCRIPTION: Summary about the check, as a string.
- CATEGORIES: Categories relative to the check, as a list of symbol.
They are used for filtering when calling `org-lint'. Checkers not
explicitly associated to a category are collected in the `default'
one.
- TRUST: The trust level one can have in the check. It is either `low'
or `high', depending on the heuristics implemented and the nature of
the check. This has an indicative value only and is displayed along
reports.
All checks have to be listed in `org-lint--checkers'.
Results are displayed in a special "*Org Lint*" buffer with a dedicated
major mode, derived from `tabulated-list-mode'. In addition to the usual
key-bindings inherited from it, "C-j" displays problematic line reported
under point and "RET" jumps to it.
Checks currently implemented are:
- duplicates CUSTOM_ID properties
- duplicate NAME values
- duplicate targets
- duplicate footnote definitions
- orphaned affiliated keywords
- obsolete affiliated keywords
- missing language in src blocks
- NAME values with a colon
- wrong header arguments in src blocks
- misuse of CATEGORY keyword
- "coderef" links with unknown destination
- "custom-id" links with unknown destination
- "fuzzy" links with unknown destination
- "id" links with unknown destination
- links to non-existent local files
- special properties in properties drawer
- obsolete syntax for PROPERTIES drawers
- missing definition for footnote references
- missing reference for footnote definitions
- non-footnote definitions in footnote section
- probable invalid keywords
- invalid blocks
- probable incomplete drawers
- obsolete QUOTE section
Since it relies on lexical binding, `pcase' and `string-prefix-p', it
cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
useful enough.
Feedback welcome.
Regards,
--
Nicolas Goaziou 0x80A93738
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Implement-Org-linting.patch --]
[-- Type: text/x-diff, Size: 24656 bytes --]
From 8324f1422953caab5566950f989e95fd4325a0b0 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Date: Wed, 15 Apr 2015 22:24:15 +0200
Subject: [PATCH] Implement Org linting
* lisp/org-lint.el: New file.
---
lisp/org-lint.el | 681 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 681 insertions(+)
create mode 100644 lisp/org-lint.el
diff --git a/lisp/org-lint.el b/lisp/org-lint.el
new file mode 100644
index 0000000..009a503
--- /dev/null
+++ b/lisp/org-lint.el
@@ -0,0 +1,681 @@
+;;; org-lint.el --- Linting for Org documents -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015 Free Software Foundation
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+;; Keywords: outlines, hypermedia, calendar, wp
+
+;; 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:
+
+;; This library implements linting for Org syntax. The sole public
+;; function is `org-lint', which see.
+
+;; Internally, the library defines a new structure:
+;; `org-lint-checker', with the following slots:
+
+;; - NAME: Unique check identifier, as a symbol. The check is done
+;; calling the function `org-lint-NAME' with one mandatory
+;; argument, the parse tree describing the current Org buffer.
+;; Such function calls are wrapped within a `save-excursion' and
+;; point is always at `point-min'. Its return value has to be an
+;; alist (POSITION MESSAGE) when POSITION refer to the buffer
+;; position of the error, as an integer, and MESSAGE is a strings
+;; describing the error.
+
+;; - DESCRIPTION: Summary about the check, as a string.
+
+;; - CATEGORIES: Categories relative to the check, as a list of
+;; symbol. They are used for filtering when calling `org-lint'.
+;; Checkers not explicitly associated to a category are collected
+;; in the `default' one.
+
+;; - TRUST: The trust level one can have in the check. It is either
+;; `low' or `high', depending on the heuristics implemented and
+;; the nature of the check. This has an indicative value only and
+;; is displayed along reports.
+
+;; All checks have to be listed in `org-lint--checkers'.
+
+;; Results are displayed in a special "*Org Lint*" buffer with
+;; a dedicated major mode, derived from `tabulated-list-mode'. In
+;; addition to the usual key-bindings inherited from it, "C-j"
+;; displays problematic line reported under point and "RET" jumps to
+;; it.
+
+;; Checks currently implemented are:
+
+;; - duplicates CUSTOM_ID properties
+;; - duplicate NAME values
+;; - duplicate targets
+;; - duplicate footnote definitions
+;; - orphaned affiliated keywords
+;; - obsolete affiliated keywords
+;; - missing language in src blocks
+;; - NAME values with a colon
+;; - wrong header arguments in src blocks
+;; - misuse of CATEGORY keyword
+;; - "coderef" links with unknown destination
+;; - "custom-id" links with unknown destination
+;; - "fuzzy" links with unknown destination
+;; - "id" links with unknown destination
+;; - links to non-existent local files
+;; - special properties in properties drawer
+;; - obsolete syntax for PROPERTIES drawers
+;; - missing definition for footnote references
+;; - missing reference for footnote definitions
+;; - non-footnote definitions in footnote section
+;; - probable invalid keywords
+;; - invalid blocks
+;; - probable incomplete drawers
+;; - obsolete QUOTE section
+
+\f
+;;; Code:
+
+(require 'cl-lib)
+(require 'org-element)
+(require 'ox)
+(require 'ob)
+
+\f
+;;; Checkers
+
+(cl-defstruct (org-lint-checker (:copier nil))
+ (name 'missing-checker-name)
+ (description "")
+ (categories '(default))
+ (trust 'high)) ; `low' or `high'
+
+(defun org-lint-missing-checker-name (_)
+ (error
+ "`A checker has no `:name' property. Please verify `org-lint--checkers'"))
+
+(defconst org-lint--checkers
+ (list
+ (make-org-lint-checker
+ :name 'duplicate-custom-id
+ :description "Report duplicates CUSTOM_ID properties"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'duplicate-name
+ :description "Report duplicate NAME values"
+ :categories '(babel link))
+ (make-org-lint-checker
+ :name 'duplicate-target
+ :description "Report duplicate targets"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'duplicate-footnote-definition
+ :description "Report duplicate footnote definitions"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'orphaned-affiliated-keywords
+ :description "Report orphaned affiliated keywords"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'obsolete-affiliated-keywords
+ :description "Report obsolete affiliated keywords"
+ :categories '(obsolete))
+ (make-org-lint-checker
+ :name 'missing-language-in-src-block
+ :description "Report missing language in src blocks"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'colon-in-name
+ :description "Report NAME values with a colon"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'wrong-header-argument
+ :description "Report wrong header arguments in src blocks"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'deprecated-category-setup
+ :description "Report misuse of CATEGORY keyword"
+ :categories '(obsolete))
+ (make-org-lint-checker
+ :name 'invalid-coderef-link
+ :description "Report \"coderef\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-custom-id-link
+ :description "Report \"custom-id\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-fuzzy-link
+ :description "Report \"fuzzy\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-id-link
+ :description "Report \"id\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'link-to-local-file
+ :description "Report links to non-existent local files"
+ :categories '(link)
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'special-property-in-properties-drawer
+ :description "Report special properties in properties drawers"
+ :categories '(properties))
+ (make-org-lint-checker
+ :name 'obsolete-properties-drawer
+ :description "Report obsolete syntax for properties drawers"
+ :categories '(obsolete properties)
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'undefined-footnote-reference
+ :description "Report missing definition for footnote references"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'unreferenced-footnote-definition
+ :description "Report missing reference for footnote definitions"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'extraneous-element-in-footnote-section
+ :description "Report non-footnote definitions in footnote section"
+ :trust 'high
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'invalid-keyword-syntax
+ :description "Report probable invalid keywords"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'corrupted-block
+ :description "Report invalid blocks"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'incomplete-drawer
+ :description "Report probable incomplete drawers"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'quote-section
+ :description "Report obsolete QUOTE section"
+ :categories '(obsolete)
+ :trust 'low))
+ "List of all available checkers.")
+
+(defun org-lint-duplicate-custom-id (ast)
+ (org-element-map ast '(headline inlinetask)
+ (let (ids)
+ (lambda (e)
+ (let ((custom-id (org-element-property :CUSTOM_ID e)))
+ (cond
+ ((not custom-id) nil)
+ ((member custom-id ids)
+ (list (org-element-map e 'node-property
+ (lambda (p)
+ (and (eq (compare-strings
+ "CUSTOM_ID" nil nil
+ (org-element-property :key p) nil nil
+ t)
+ t)
+ (org-element-property :begin p)))
+ nil t)
+ (format "Duplicate CUSTOM_ID property \"%s\"" custom-id)))
+ (t (push custom-id ids) nil)))))))
+
+(defun org-lint-duplicate-name (ast)
+ (org-element-map ast org-element-all-elements
+ (let (names)
+ (lambda (e)
+ (let ((name (org-element-property :name e)))
+ (cond
+ ((not name) nil)
+ ((member name names)
+ (list (progn (goto-char (org-element-property :begin e))
+ (let ((case-fold-search t))
+ (re-search-forward
+ (concat "^[ \t]*#\\+NAME: +" (regexp-quote name)))
+ (match-beginning 0)))
+ (format "Duplicate NAME \"%s\"" name)))
+ (t (push name names) nil)))))))
+
+(defun org-lint-duplicate-target (ast)
+ (org-element-map ast 'target
+ (let (targets)
+ (lambda (o)
+ (let ((target (org-split-string (org-element-property :value o))))
+ (if (member target targets)
+ (list (org-element-property :begin o)
+ (format "Duplicate target \"%s\""
+ (org-element-property :value o)))
+ (push target targets)
+ nil))))))
+
+(defun org-lint-duplicate-footnote-definition (ast)
+ (org-element-map ast 'footnote-definition
+ (let (labels)
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (cond ((not label) nil)
+ ((member label labels)
+ (list (org-element-property :post-affiliated f)
+ (format "Duplicate footnote definition \"%s\"" label)))
+ (t (push label labels) nil)))))))
+
+(defun org-lint-orphaned-affiliated-keywords (ast)
+ (org-element-map ast 'keyword
+ (lambda (k)
+ (let ((key (org-element-property :key k)))
+ (and (member key org-element-affiliated-keywords)
+ (list (org-element-property :post-affiliated k)
+ (format "Orphaned affiliated keyword: \"%s\"" key)))))))
+
+(defun org-lint-obsolete-affiliated-keywords (_)
+ (let ((regexp (format "^[ \t]*#\\+%s:"
+ (regexp-opt '("DATA" "LABEL" "RESNAME" "SOURCE"
+ "SRCNAME" "TBLNAME" "RESULT" "HEADERS")
+ t)))
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((key (upcase (org-match-string-no-properties 1))))
+ (when (< (point)
+ (org-element-property :post-affiliated (org-element-at-point)))
+ (push
+ (list (line-beginning-position)
+ (format
+ "Obsolete affiliated keyword: \"%s\". Use \"%s\" instead"
+ key
+ (pcase key
+ ("HEADERS" "HEADER")
+ ("RESULT" "RESULTS")
+ (_ "NAME"))))
+ reports))))
+ reports))
+
+(defun org-lint-missing-language-in-src-block (ast)
+ (org-element-map ast 'src-block
+ (lambda (b)
+ (unless (org-element-property :language b)
+ (list (org-element-property :post-affiliated b)
+ "Missing language in source block")))))
+
+(defun org-lint-deprecated-category-setup (ast)
+ (org-element-map ast 'keyword
+ (let (category-flag)
+ (lambda (k)
+ (cond
+ ((not (string= (org-element-property :key k) "CATEGORY")) nil)
+ (category-flag
+ (list (org-element-property :post-affiliated k)
+ "Spurious CATEGORY keyword. Set :CATEGORY: property instead"))
+ (t (setf category-flag t) nil))))))
+
+(defun org-lint-invalid-coderef-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (let ((ref (org-element-property :path link)))
+ (and (equal (org-element-property :type link) "coderef")
+ (not (ignore-errors (org-export-resolve-coderef ref info)))
+ (list (org-element-property :begin link)
+ (format "Unknown coderef \"%s\"" ref))))))))
+
+(defun org-lint-invalid-custom-id-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (and (equal (org-element-property :type link) "custom-id")
+ (not (ignore-errors (org-export-resolve-id-link link info)))
+ (list (org-element-property :begin link)
+ (format "Unknown custom ID \"%s\""
+ (org-element-property :path link))))))))
+
+(defun org-lint-invalid-fuzzy-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (and (equal (org-element-property :type link) "fuzzy")
+ (not (ignore-errors (org-export-resolve-fuzzy-link link info)))
+ (list (org-element-property :begin link)
+ (format "Unknown fuzzy location \"%s\""
+ (let ((path (org-element-property :path link)))
+ (if (string-prefix-p "*" path)
+ (substring path 1)
+ path)))))))))
+
+(defun org-lint-invalid-id-link (ast)
+ (org-element-map ast 'link
+ (lambda (link)
+ (let ((id (org-element-property :path link)))
+ (and (equal (org-element-property :type link) "id")
+ (not (org-id-find id))
+ (list (org-element-property :begin link)
+ (format "Unknown ID \"%s\"" id)))))))
+
+(defun org-lint-special-property-in-properties-drawer (ast)
+ (org-element-map ast 'node-property
+ (lambda (p)
+ (let ((key (org-element-property :key p)))
+ (and (member-ignore-case key org-special-properties)
+ (list (org-element-property :begin p)
+ (format
+ "Special property \"%s\" found in a properties drawer"
+ key)))))))
+
+(defun org-lint-obsolete-properties-drawer (ast)
+ (org-element-map ast 'drawer
+ (lambda (d)
+ (when (equal (org-element-property :drawer-name d) "PROPERTIES")
+ (let ((section (org-element-lineage d '(section))))
+ (unless (org-element-map section 'property-drawer #'identity nil t)
+ (list (org-element-property :post-affiliated d)
+ (if (save-excursion
+ (goto-char (org-element-property :post-affiliated d))
+ (forward-line -1)
+ (or (org-at-heading-p) (org-at-planning-p)))
+ "Incorrect contents for PROPERTIES drawer"
+ "Incorrect location for PROPERTIES drawer"))))))))
+
+(defun org-lint-link-to-local-file (ast)
+ (org-element-map ast 'link
+ (lambda (l)
+ (when (equal (org-element-property :type l) "file")
+ (let ((file (org-element-property :path l)))
+ (and (not (file-remote-p file))
+ (not (file-exists-p file))
+ (list (org-element-property :begin l)
+ (format "Link to non-existent local file \"%s\""
+ file))))))))
+
+(defun org-lint-undefined-footnote-reference (ast)
+ (let ((definitions (org-element-map ast 'footnote-definition
+ (lambda (f) (org-element-property :label f)))))
+ (org-element-map ast 'footnote-reference
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (and label
+ (not (member label definitions))
+ (list (org-element-property :begin f)
+ (format "Missing definition for footnote [%s]"
+ label))))))))
+
+(defun org-lint-unreferenced-footnote-definition (ast)
+ (let ((references (org-element-map ast 'footnote-reference
+ (lambda (f) (org-element-property :label f)))))
+ (org-element-map ast 'footnote-definition
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (and label
+ (not (member label references))
+ (list (org-element-property :post-affiliated f)
+ (format "No reference for footnote definition [%s]"
+ label))))))))
+
+(defun org-lint-colon-in-name (ast)
+ (org-element-map ast org-element-all-elements
+ (lambda (e)
+ (let ((name (org-element-property :name e)))
+ (and name
+ (org-string-match-p ":" name)
+ (list (progn
+ (goto-char (org-element-property :begin e))
+ (let ((case-fold-search t))
+ (re-search-forward
+ (concat "^[ \t]*#\\+NAME: +" (regexp-quote name)))
+ (match-beginning 0)))
+ (format
+ "Name \"%s\" contains a colon; Babel cannot use it as input"
+ name)))))))
+
+(defun org-lint-incomplete-drawer (_)
+ (let (reports)
+ (while (re-search-forward org-drawer-regexp nil t)
+ (let ((name (org-trim (org-match-string-no-properties 0)))
+ (element (org-element-at-point)))
+ (pcase (org-element-type element)
+ (`(drawer property-drawer)
+ (goto-char (org-element-property :end element))
+ nil)
+ (`paragraph
+ (push (list (line-beginning-position)
+ (format "Possible incomplete drawer \"%s\"" name))
+ reports))
+ (_ nil))))
+ reports))
+
+(defun org-lint-corrupted-block (_)
+ (let ((case-fold-search t)
+ (regexp "^[ \t]*#\\+\\(BEGIN\\|END\\)\\(?::\\|_[^[:space:]]*\\)?[ \t]*")
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((name (org-trim (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position)))))
+ (cond
+ ((and (string-prefix-p "END" (match-string 1) t)
+ (not (eolp)))
+ (push (list (line-beginning-position)
+ (format "Invalid block closing line \"%s\"" name))
+ reports))
+ ((eq (org-element-type (org-element-at-point)) 'paragraph)
+ (push (list (line-beginning-position)
+ (format "Possible incomplete block \"%s\""
+ name))
+ reports)))))
+ reports))
+
+(defun org-lint-invalid-keyword-syntax (_)
+ (let ((regexp "^[ \t]*\\(#\\+[^[:space:]:]*\\)\\(?:[[:space:]]\\|$\\)")
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((name (org-match-string-no-properties 1)))
+ (unless (or (string-prefix-p "#+BEGIN" name t)
+ (string-prefix-p "#+END" name t))
+ (push (list (match-beginning 0)
+ (format "Possible missing colon in keyword \"%s\"" name))
+ reports))))
+ reports))
+
+(defun org-lint-extraneous-element-in-footnote-section (ast)
+ (org-element-map ast 'headline
+ (lambda (h)
+ (and (org-element-property :footnote-section-p h)
+ (org-element-map (org-element-contents h)
+ (org-remove-if
+ (lambda (e)
+ (memq e '(comment comment-block footnote-definition
+ property-drawer section)))
+ org-element-all-elements)
+ (lambda (e)
+ (not (and (eq (org-element-type e) 'headline)
+ (org-element-property :commentedp e))))
+ nil t '(footnote-definition property-drawer))
+ (list (org-element-property :begin h)
+ "Extraneous elements in footnote section")))))
+
+(defun org-lint-quote-section (ast)
+ (org-element-map ast '(headline inlinetask)
+ (lambda (h)
+ (let ((title (org-element-property :raw-value h)))
+ (and (or (string-prefix-p "QUOTE " title)
+ (string-prefix-p (concat org-comment-string " QUOTE ") title))
+ (list (org-element-property :begin h)
+ "Deprecated QUOTE section"))))))
+
+(defun org-lint-wrong-header-argument (ast)
+ (let (reports)
+ (org-element-map ast 'src-block
+ (lambda (b)
+ (let* ((language (org-element-property :language b))
+ (allowed
+ (mapcar #'symbol-name
+ (append
+ org-babel-header-arg-names
+ (let ((v (intern (concat "org-babel-header-args:"
+ language))))
+ (and (boundp v)
+ (mapcar #'car (symbol-value v))))))))
+ (dolist (header (mapcar
+ (lambda (e) (substring (symbol-name (car e)) 1))
+ (org-babel-parse-header-arguments
+ (org-element-property :parameters b))))
+ (unless (member header allowed)
+ (push (list (org-element-property :post-affiliated b)
+ (format "Unknown header argument \"%s\"" header))
+ reports))))))
+ reports))
+
+\f
+;;; Reports UI
+
+(defvar org-lint--report-mode-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map tabulated-list-mode-map)
+ (define-key map (kbd "RET") 'org-lint--jump-to-source)
+ (define-key map (kbd "C-j") 'org-lint--show-source)
+ map)
+ "Local keymap for `org-lint--report-mode' buffers.")
+
+(define-derived-mode org-lint--report-mode tabulated-list-mode "OrgLint"
+ "Major mode used to display reports emitted during linting.
+\\<package-menu-mode-map>"
+ (setf tabulated-list-format
+ `[("Line" 6
+ (lambda (a b)
+ (< (string-to-number (aref (cadr a) 0))
+ (string-to-number (aref (cadr b) 0))))
+ :right-align t)
+ ("Trust" 5 t)
+ ("Warning" 0 nil)])
+ (tabulated-list-init-header))
+
+(defun org-lint--generate-reports (checkers)
+ "Run all CHECKERS in current buffer.
+Return an alist (ID [LINE TRUST DESCRIPTION]), suitable for
+`tabulated-list-printer'."
+ (save-excursion
+ (goto-char (point-min))
+ (let ((ast (org-element-parse-buffer))
+ (id 0)
+ (last-line 1)
+ (last-pos 1))
+ ;; Insert unique ID for each report. Replace buffer positions
+ ;; with line numbers.
+ (mapcar
+ (lambda (report)
+ (list
+ (incf id)
+ (apply #'vector
+ (cons
+ (progn
+ (goto-char (car report))
+ (beginning-of-line)
+ (prog1 (number-to-string
+ (incf last-line (count-lines last-pos (point))))
+ (setf last-pos (point))))
+ (cdr report)))))
+ ;; Insert trust level in generated reports. Also sort them by
+ ;; buffer position in order to optimize lines computation.
+ (sort (cl-mapcan
+ (lambda (c)
+ (let ((trust (symbol-name (org-lint-checker-trust c))))
+ (mapcar
+ (lambda (report) (list (car report) trust (nth 1 report)))
+ (save-excursion
+ (funcall (intern
+ (concat "org-lint-"
+ (symbol-name (org-lint-checker-name c))))
+ ast)))))
+ checkers)
+ #'car-less-than-car)))))
+
+(defvar org-lint--source-buffer nil
+ "Source buffer associated to current report buffer.")
+(make-variable-buffer-local 'org-lint--source-buffer)
+
+(defun org-lint--display-reports (source checkers)
+ "Display linting reports for buffer SOURCE.
+CHECKERS is the list of checkers used."
+ (let ((buffer (get-buffer-create "*Org Lint*")))
+ (with-current-buffer buffer
+ (org-lint--report-mode)
+ (setf org-lint--source-buffer source)
+ (setf tabulated-list-entries
+ (lambda ()
+ (with-current-buffer source
+ (org-lint--generate-reports checkers))))
+ (tabulated-list-print))
+ (pop-to-buffer buffer)))
+
+(defun org-lint--jump-to-source ()
+ "Move to source line that generated the report at point."
+ (interactive)
+ (let ((l (string-to-number (aref (tabulated-list-get-entry) 0))))
+ (switch-to-buffer-other-window org-lint--source-buffer)
+ (org-goto-line l)
+ (org-show-set-visibility 'local)
+ (recenter)))
+
+(defun org-lint--show-source ()
+ "Show source line that generated the report at point."
+ (interactive)
+ (let ((buffer (current-buffer))
+ (l (string-to-number (aref (tabulated-list-get-entry) 0))))
+ (switch-to-buffer-other-window org-lint--source-buffer)
+ (org-goto-line l)
+ (org-show-set-visibility 'local)
+ (recenter)
+ (switch-to-buffer-other-window buffer)))
+
+\f
+;;; Public function
+
+;;;###autoload
+(defun org-lint (&optional arg)
+ "Check current Org buffer for syntax mistakes.
+
+By default, run all checkers. With a single prefix ARG \
+\\[universal-argument],
+select one category of checkers only. With a double prefix
+\\[universal-argument] \\[universal-argument], select one precise \
+checker by its name.
+
+ARG can also be a list of checker names, as symbols, to run."
+ (interactive "P")
+ (unless (derived-mode-p 'org-mode) (user-error "Not in an Org buffer"))
+ (message "Org linting process starting...")
+ (org-lint--display-reports
+ (current-buffer)
+ (pcase arg
+ (`nil org-lint--checkers)
+ (`(4)
+ (let ((category
+ (completing-read
+ "Checker category: "
+ (mapcar #'org-lint-checker-categories org-lint--checkers)
+ nil t)))
+ (org-remove-if-not
+ (lambda (c) (assoc-string (org-lint-checker-categories c) category))
+ org-lint--checkers)))
+ (`(16)
+ (list
+ (let ((name (completing-read
+ "Checker name: "
+ (mapcar #'org-lint-checker-name org-lint--checkers)
+ nil t)))
+ (catch 'exit
+ (dolist (c org-lint--checkers)
+ (when (string= (org-lint-checker-name c) name)
+ (throw 'exit c)))))))
+ ((pred consp)
+ (org-remove-if-not (lambda (c) (memq (org-lint-checker-name c) arg))
+ org-lint--checkers))
+ (_ (user-error "Invalid argument `%S' for `org-lint'" arg))))
+ (message "Org linting process completed"))
+
+
+(provide 'org-lint)
+;;; org-lint.el ends here
--
2.3.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
@ 2015-04-19 14:23 ` Rasmus
2015-04-19 16:24 ` Nicolas Goaziou
2015-04-19 19:32 ` Marco Wahl
` (6 subsequent siblings)
7 siblings, 1 reply; 53+ messages in thread
From: Rasmus @ 2015-04-19 14:23 UTC (permalink / raw)
To: emacs-orgmode
Hi,
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
> useful enough.
It looks like a great tool. Especially given the fact that the org format
still seems to be developing.
Anyway, some very premature notes:
One venue that may worth pursuing is better error messages during export,
when links do not exist. E.g. after a link fails to resolve, an org-lint
buffer is opened to ease tracking down the error.
Perhaps, org-lint should also check that INCLUDE keywords correctly
resolves, e.g. whether #section exits in file.org:
#+INCLUDE: "file.org::#section"
Perhaps that would induce nasty recursions, though...
Thanks,
Rasmus
--
Enough with the bla bla!
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 14:23 ` Rasmus
@ 2015-04-19 16:24 ` Nicolas Goaziou
0 siblings, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-04-19 16:24 UTC (permalink / raw)
To: Rasmus; +Cc: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 1018 bytes --]
Rasmus <rasmus@gmx.us> writes:
> It looks like a great tool. Especially given the fact that the org format
> still seems to be developing.
Indeed. We can use it as another channel for syntax deprecation.
> Anyway, some very premature notes:
>
> One venue that may worth pursuing is better error messages during export,
> when links do not exist. E.g. after a link fails to resolve, an org-lint
> buffer is opened to ease tracking down the error.
I think the error message during export is as good as the one provided
by `org-lint', minus the line and the jump.
> Perhaps, org-lint should also check that INCLUDE keywords correctly
> resolves, e.g. whether #section exits in file.org:
>
> #+INCLUDE: "file.org::#section"
Good idea. I implemented it along with a check for SETUPFILE keywords.
Updated file attached.
> Perhaps that would induce nasty recursions, though...
`org-lint' only checks current document, it doesn't enter INCLUDE files,
so there's no danger here.
Thanks for the feedback.
Regards,
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Implement-Org-linting.patch --]
[-- Type: text/x-diff, Size: 27156 bytes --]
From 1b182320599a435de7ab85f64ba984d1e5ef4502 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Date: Wed, 15 Apr 2015 22:24:15 +0200
Subject: [PATCH] Implement Org linting
* lisp/org-lint.el: New file.
---
lisp/org-lint.el | 748 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 748 insertions(+)
create mode 100644 lisp/org-lint.el
diff --git a/lisp/org-lint.el b/lisp/org-lint.el
new file mode 100644
index 0000000..a514b8b
--- /dev/null
+++ b/lisp/org-lint.el
@@ -0,0 +1,748 @@
+;;; org-lint.el --- Linting for Org documents -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015 Free Software Foundation
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+;; Keywords: outlines, hypermedia, calendar, wp
+
+;; 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:
+
+;; This library implements linting for Org syntax. The sole public
+;; function is `org-lint', which see.
+
+;; Internally, the library defines a new structure:
+;; `org-lint-checker', with the following slots:
+
+;; - NAME: Unique check identifier, as a symbol. The check is done
+;; calling the function `org-lint-NAME' with one mandatory
+;; argument, the parse tree describing the current Org buffer.
+;; Such function calls are wrapped within a `save-excursion' and
+;; point is always at `point-min'. Its return value has to be an
+;; alist (POSITION MESSAGE) when POSITION refer to the buffer
+;; position of the error, as an integer, and MESSAGE is a strings
+;; describing the error.
+
+;; - DESCRIPTION: Summary about the check, as a string.
+
+;; - CATEGORIES: Categories relative to the check, as a list of
+;; symbol. They are used for filtering when calling `org-lint'.
+;; Checkers not explicitly associated to a category are collected
+;; in the `default' one.
+
+;; - TRUST: The trust level one can have in the check. It is either
+;; `low' or `high', depending on the heuristics implemented and
+;; the nature of the check. This has an indicative value only and
+;; is displayed along reports.
+
+;; All checks have to be listed in `org-lint--checkers'.
+
+;; Results are displayed in a special "*Org Lint*" buffer with
+;; a dedicated major mode, derived from `tabulated-list-mode'. In
+;; addition to the usual key-bindings inherited from it, "C-j"
+;; displays problematic line reported under point and "RET" jumps to
+;; it.
+
+;; Checks currently implemented are:
+
+;; - duplicates CUSTOM_ID properties
+;; - duplicate NAME values
+;; - duplicate targets
+;; - duplicate footnote definitions
+;; - orphaned affiliated keywords
+;; - obsolete affiliated keywords
+;; - missing language in src blocks
+;; - NAME values with a colon
+;; - wrong header arguments in src blocks
+;; - misuse of CATEGORY keyword
+;; - "coderef" links with unknown destination
+;; - "custom-id" links with unknown destination
+;; - "fuzzy" links with unknown destination
+;; - "id" links with unknown destination
+;; - links to non-existent local files
+;; - SETUPFILE keywords with non-existent file parameter
+;; - INCLUDE keywords with wrong link parameter
+;; - special properties in properties drawer
+;; - obsolete syntax for PROPERTIES drawers
+;; - missing definition for footnote references
+;; - missing reference for footnote definitions
+;; - non-footnote definitions in footnote section
+;; - probable invalid keywords
+;; - invalid blocks
+;; - probable incomplete drawers
+;; - obsolete QUOTE section
+
+\f
+;;; Code:
+
+(require 'cl-lib)
+(require 'org-element)
+(require 'ox)
+(require 'ob)
+
+\f
+;;; Checkers
+
+(cl-defstruct (org-lint-checker (:copier nil))
+ (name 'missing-checker-name)
+ (description "")
+ (categories '(default))
+ (trust 'high)) ; `low' or `high'
+
+(defun org-lint-missing-checker-name (_)
+ (error
+ "`A checker has no `:name' property. Please verify `org-lint--checkers'"))
+
+(defconst org-lint--checkers
+ (list
+ (make-org-lint-checker
+ :name 'duplicate-custom-id
+ :description "Report duplicates CUSTOM_ID properties"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'duplicate-name
+ :description "Report duplicate NAME values"
+ :categories '(babel link))
+ (make-org-lint-checker
+ :name 'duplicate-target
+ :description "Report duplicate targets"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'duplicate-footnote-definition
+ :description "Report duplicate footnote definitions"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'orphaned-affiliated-keywords
+ :description "Report orphaned affiliated keywords"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'obsolete-affiliated-keywords
+ :description "Report obsolete affiliated keywords"
+ :categories '(obsolete))
+ (make-org-lint-checker
+ :name 'missing-language-in-src-block
+ :description "Report missing language in src blocks"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'colon-in-name
+ :description "Report NAME values with a colon"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'wrong-header-argument
+ :description "Report wrong header arguments in src blocks"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'deprecated-category-setup
+ :description "Report misuse of CATEGORY keyword"
+ :categories '(obsolete))
+ (make-org-lint-checker
+ :name 'invalid-coderef-link
+ :description "Report \"coderef\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-custom-id-link
+ :description "Report \"custom-id\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-fuzzy-link
+ :description "Report \"fuzzy\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-id-link
+ :description "Report \"id\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'link-to-local-file
+ :description "Report links to non-existent local files"
+ :categories '(link)
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'non-existent-setupfile-parameter
+ :description "Report SETUPFILE keywords with non-existent file parameter"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'wrong-include-link-parameter
+ :description "Report INCLUDE keywords with misleading link parameter"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'special-property-in-properties-drawer
+ :description "Report special properties in properties drawers"
+ :categories '(properties))
+ (make-org-lint-checker
+ :name 'obsolete-properties-drawer
+ :description "Report obsolete syntax for properties drawers"
+ :categories '(obsolete properties)
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'undefined-footnote-reference
+ :description "Report missing definition for footnote references"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'unreferenced-footnote-definition
+ :description "Report missing reference for footnote definitions"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'extraneous-element-in-footnote-section
+ :description "Report non-footnote definitions in footnote section"
+ :trust 'high
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'invalid-keyword-syntax
+ :description "Report probable invalid keywords"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'corrupted-block
+ :description "Report invalid blocks"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'incomplete-drawer
+ :description "Report probable incomplete drawers"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'quote-section
+ :description "Report obsolete QUOTE section"
+ :categories '(obsolete)
+ :trust 'low))
+ "List of all available checkers.")
+
+(defun org-lint-duplicate-custom-id (ast)
+ (org-element-map ast '(headline inlinetask)
+ (let (ids)
+ (lambda (e)
+ (let ((custom-id (org-element-property :CUSTOM_ID e)))
+ (cond
+ ((not custom-id) nil)
+ ((member custom-id ids)
+ (list (org-element-map e 'node-property
+ (lambda (p)
+ (and (eq (compare-strings
+ "CUSTOM_ID" nil nil
+ (org-element-property :key p) nil nil
+ t)
+ t)
+ (org-element-property :begin p)))
+ nil t)
+ (format "Duplicate CUSTOM_ID property \"%s\"" custom-id)))
+ (t (push custom-id ids) nil)))))))
+
+(defun org-lint-duplicate-name (ast)
+ (org-element-map ast org-element-all-elements
+ (let (names)
+ (lambda (e)
+ (let ((name (org-element-property :name e)))
+ (cond
+ ((not name) nil)
+ ((member name names)
+ (list (progn (goto-char (org-element-property :begin e))
+ (let ((case-fold-search t))
+ (re-search-forward
+ (concat "^[ \t]*#\\+NAME: +" (regexp-quote name)))
+ (match-beginning 0)))
+ (format "Duplicate NAME \"%s\"" name)))
+ (t (push name names) nil)))))))
+
+(defun org-lint-duplicate-target (ast)
+ (org-element-map ast 'target
+ (let (targets)
+ (lambda (o)
+ (let ((target (org-split-string (org-element-property :value o))))
+ (if (member target targets)
+ (list (org-element-property :begin o)
+ (format "Duplicate target \"%s\""
+ (org-element-property :value o)))
+ (push target targets)
+ nil))))))
+
+(defun org-lint-duplicate-footnote-definition (ast)
+ (org-element-map ast 'footnote-definition
+ (let (labels)
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (cond ((not label) nil)
+ ((member label labels)
+ (list (org-element-property :post-affiliated f)
+ (format "Duplicate footnote definition \"%s\"" label)))
+ (t (push label labels) nil)))))))
+
+(defun org-lint-orphaned-affiliated-keywords (ast)
+ (org-element-map ast 'keyword
+ (lambda (k)
+ (let ((key (org-element-property :key k)))
+ (and (member key org-element-affiliated-keywords)
+ (list (org-element-property :post-affiliated k)
+ (format "Orphaned affiliated keyword: \"%s\"" key)))))))
+
+(defun org-lint-obsolete-affiliated-keywords (_)
+ (let ((regexp (format "^[ \t]*#\\+%s:"
+ (regexp-opt '("DATA" "LABEL" "RESNAME" "SOURCE"
+ "SRCNAME" "TBLNAME" "RESULT" "HEADERS")
+ t)))
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((key (upcase (org-match-string-no-properties 1))))
+ (when (< (point)
+ (org-element-property :post-affiliated (org-element-at-point)))
+ (push
+ (list (line-beginning-position)
+ (format
+ "Obsolete affiliated keyword: \"%s\". Use \"%s\" instead"
+ key
+ (pcase key
+ ("HEADERS" "HEADER")
+ ("RESULT" "RESULTS")
+ (_ "NAME"))))
+ reports))))
+ reports))
+
+(defun org-lint-missing-language-in-src-block (ast)
+ (org-element-map ast 'src-block
+ (lambda (b)
+ (unless (org-element-property :language b)
+ (list (org-element-property :post-affiliated b)
+ "Missing language in source block")))))
+
+(defun org-lint-deprecated-category-setup (ast)
+ (org-element-map ast 'keyword
+ (let (category-flag)
+ (lambda (k)
+ (cond
+ ((not (string= (org-element-property :key k) "CATEGORY")) nil)
+ (category-flag
+ (list (org-element-property :post-affiliated k)
+ "Spurious CATEGORY keyword. Set :CATEGORY: property instead"))
+ (t (setf category-flag t) nil))))))
+
+(defun org-lint-invalid-coderef-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (let ((ref (org-element-property :path link)))
+ (and (equal (org-element-property :type link) "coderef")
+ (not (ignore-errors (org-export-resolve-coderef ref info)))
+ (list (org-element-property :begin link)
+ (format "Unknown coderef \"%s\"" ref))))))))
+
+(defun org-lint-invalid-custom-id-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (and (equal (org-element-property :type link) "custom-id")
+ (not (ignore-errors (org-export-resolve-id-link link info)))
+ (list (org-element-property :begin link)
+ (format "Unknown custom ID \"%s\""
+ (org-element-property :path link))))))))
+
+(defun org-lint-invalid-fuzzy-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (and (equal (org-element-property :type link) "fuzzy")
+ (not (ignore-errors (org-export-resolve-fuzzy-link link info)))
+ (list (org-element-property :begin link)
+ (format "Unknown fuzzy location \"%s\""
+ (let ((path (org-element-property :path link)))
+ (if (string-prefix-p "*" path)
+ (substring path 1)
+ path)))))))))
+
+(defun org-lint-invalid-id-link (ast)
+ (org-element-map ast 'link
+ (lambda (link)
+ (let ((id (org-element-property :path link)))
+ (and (equal (org-element-property :type link) "id")
+ (not (org-id-find id))
+ (list (org-element-property :begin link)
+ (format "Unknown ID \"%s\"" id)))))))
+
+(defun org-lint-special-property-in-properties-drawer (ast)
+ (org-element-map ast 'node-property
+ (lambda (p)
+ (let ((key (org-element-property :key p)))
+ (and (member-ignore-case key org-special-properties)
+ (list (org-element-property :begin p)
+ (format
+ "Special property \"%s\" found in a properties drawer"
+ key)))))))
+
+(defun org-lint-obsolete-properties-drawer (ast)
+ (org-element-map ast 'drawer
+ (lambda (d)
+ (when (equal (org-element-property :drawer-name d) "PROPERTIES")
+ (let ((section (org-element-lineage d '(section))))
+ (unless (org-element-map section 'property-drawer #'identity nil t)
+ (list (org-element-property :post-affiliated d)
+ (if (save-excursion
+ (goto-char (org-element-property :post-affiliated d))
+ (forward-line -1)
+ (or (org-at-heading-p) (org-at-planning-p)))
+ "Incorrect contents for PROPERTIES drawer"
+ "Incorrect location for PROPERTIES drawer"))))))))
+
+(defun org-lint-link-to-local-file (ast)
+ (org-element-map ast 'link
+ (lambda (l)
+ (when (equal (org-element-property :type l) "file")
+ (let ((file (org-element-property :path l)))
+ (and (not (file-remote-p file))
+ (not (file-exists-p file))
+ (list (org-element-property :begin l)
+ (format "Link to non-existent local file \"%s\""
+ file))))))))
+
+(defun org-lint-non-existent-setupfile-parameter (ast)
+ (org-element-map ast 'keyword
+ (lambda (k)
+ (when (equal (org-element-property :key k) "SETUPFILE")
+ (let ((file (org-remove-double-quotes
+ (org-element-property :value k))))
+ (and (not (file-remote-p file))
+ (not (file-exists-p file))
+ (list (org-element-property :begin k)
+ (format "Non-existent setup file \"%s\"" file))))))))
+
+(defun org-lint-wrong-include-link-parameter (ast)
+ (let (reports)
+ (org-element-map ast 'keyword
+ (lambda (k)
+ (when (equal (org-element-property :key k) "INCLUDE")
+ (let* ((value (org-element-property :value k))
+ (path
+ (and (string-match "^\\(\".+\"\\|\\S-+\\)[ \t]*" value)
+ (save-match-data
+ (org-remove-double-quotes (match-string 1 value))))))
+ (if (not path)
+ (push (list (org-element-property :post-affiliated k)
+ "Missing location argument in INCLUDE keyword")
+ reports)
+ (let* ((file (org-string-nw-p
+ (if (string-match "::\\(.*\\)\\'" path)
+ (substring path 0 (match-beginning 0))
+ path)))
+ (search (and (not (equal file path))
+ (org-string-nw-p (match-string 1 path)))))
+ (if (and file
+ (not (file-remote-p file))
+ (not (file-exists-p file)))
+ (push (list (org-element-property :post-affiliated k)
+ "Non-existent file argument in INCLUDE keyword")
+ reports)
+ (let* ((visiting (if file (find-buffer-visiting file)
+ (current-buffer)))
+ (buffer (or visiting (find-file-noselect file))))
+ (unwind-protect
+ (with-current-buffer buffer
+ (when (and search
+ (not
+ (ignore-errors
+ (let ((org-link-search-inhibit-query t))
+ (org-link-search search nil nil t)))))
+ (push
+ (list
+ (org-element-property :post-affiliated k)
+ (format
+ "Invalid search part \"%s\" in INCLUDE keyword"
+ search))
+ reports)))
+ (unless visiting (kill-buffer buffer)))))))))))
+ reports))
+
+(defun org-lint-undefined-footnote-reference (ast)
+ (let ((definitions (org-element-map ast 'footnote-definition
+ (lambda (f) (org-element-property :label f)))))
+ (org-element-map ast 'footnote-reference
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (and label
+ (not (member label definitions))
+ (list (org-element-property :begin f)
+ (format "Missing definition for footnote [%s]"
+ label))))))))
+
+(defun org-lint-unreferenced-footnote-definition (ast)
+ (let ((references (org-element-map ast 'footnote-reference
+ (lambda (f) (org-element-property :label f)))))
+ (org-element-map ast 'footnote-definition
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (and label
+ (not (member label references))
+ (list (org-element-property :post-affiliated f)
+ (format "No reference for footnote definition [%s]"
+ label))))))))
+
+(defun org-lint-colon-in-name (ast)
+ (org-element-map ast org-element-all-elements
+ (lambda (e)
+ (let ((name (org-element-property :name e)))
+ (and name
+ (org-string-match-p ":" name)
+ (list (progn
+ (goto-char (org-element-property :begin e))
+ (let ((case-fold-search t))
+ (re-search-forward
+ (concat "^[ \t]*#\\+NAME: +" (regexp-quote name)))
+ (match-beginning 0)))
+ (format
+ "Name \"%s\" contains a colon; Babel cannot use it as input"
+ name)))))))
+
+(defun org-lint-incomplete-drawer (_)
+ (let (reports)
+ (while (re-search-forward org-drawer-regexp nil t)
+ (let ((name (org-trim (org-match-string-no-properties 0)))
+ (element (org-element-at-point)))
+ (pcase (org-element-type element)
+ (`(drawer property-drawer)
+ (goto-char (org-element-property :end element))
+ nil)
+ (`paragraph
+ (push (list (line-beginning-position)
+ (format "Possible incomplete drawer \"%s\"" name))
+ reports))
+ (_ nil))))
+ reports))
+
+(defun org-lint-corrupted-block (_)
+ (let ((case-fold-search t)
+ (regexp "^[ \t]*#\\+\\(BEGIN\\|END\\)\\(?::\\|_[^[:space:]]*\\)?[ \t]*")
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((name (org-trim (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position)))))
+ (cond
+ ((and (string-prefix-p "END" (match-string 1) t)
+ (not (eolp)))
+ (push (list (line-beginning-position)
+ (format "Invalid block closing line \"%s\"" name))
+ reports))
+ ((eq (org-element-type (org-element-at-point)) 'paragraph)
+ (push (list (line-beginning-position)
+ (format "Possible incomplete block \"%s\""
+ name))
+ reports)))))
+ reports))
+
+(defun org-lint-invalid-keyword-syntax (_)
+ (let ((regexp "^[ \t]*\\(#\\+[^[:space:]:]*\\)\\(?:[[:space:]]\\|$\\)")
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((name (org-match-string-no-properties 1)))
+ (unless (or (string-prefix-p "#+BEGIN" name t)
+ (string-prefix-p "#+END" name t))
+ (push (list (match-beginning 0)
+ (format "Possible missing colon in keyword \"%s\"" name))
+ reports))))
+ reports))
+
+(defun org-lint-extraneous-element-in-footnote-section (ast)
+ (org-element-map ast 'headline
+ (lambda (h)
+ (and (org-element-property :footnote-section-p h)
+ (org-element-map (org-element-contents h)
+ (org-remove-if
+ (lambda (e)
+ (memq e '(comment comment-block footnote-definition
+ property-drawer section)))
+ org-element-all-elements)
+ (lambda (e)
+ (not (and (eq (org-element-type e) 'headline)
+ (org-element-property :commentedp e))))
+ nil t '(footnote-definition property-drawer))
+ (list (org-element-property :begin h)
+ "Extraneous elements in footnote section")))))
+
+(defun org-lint-quote-section (ast)
+ (org-element-map ast '(headline inlinetask)
+ (lambda (h)
+ (let ((title (org-element-property :raw-value h)))
+ (and (or (string-prefix-p "QUOTE " title)
+ (string-prefix-p (concat org-comment-string " QUOTE ") title))
+ (list (org-element-property :begin h)
+ "Deprecated QUOTE section"))))))
+
+(defun org-lint-wrong-header-argument (ast)
+ (let (reports)
+ (org-element-map ast 'src-block
+ (lambda (b)
+ (let* ((language (org-element-property :language b))
+ (allowed
+ (mapcar #'symbol-name
+ (append
+ org-babel-header-arg-names
+ (let ((v (intern (concat "org-babel-header-args:"
+ language))))
+ (and (boundp v)
+ (mapcar #'car (symbol-value v))))))))
+ (dolist (header (mapcar
+ (lambda (e) (substring (symbol-name (car e)) 1))
+ (org-babel-parse-header-arguments
+ (org-element-property :parameters b))))
+ (unless (member header allowed)
+ (push (list (org-element-property :post-affiliated b)
+ (format "Unknown header argument \"%s\"" header))
+ reports))))))
+ reports))
+
+\f
+;;; Reports UI
+
+(defvar org-lint--report-mode-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map tabulated-list-mode-map)
+ (define-key map (kbd "RET") 'org-lint--jump-to-source)
+ (define-key map (kbd "C-j") 'org-lint--show-source)
+ map)
+ "Local keymap for `org-lint--report-mode' buffers.")
+
+(define-derived-mode org-lint--report-mode tabulated-list-mode "OrgLint"
+ "Major mode used to display reports emitted during linting.
+\\<package-menu-mode-map>"
+ (setf tabulated-list-format
+ `[("Line" 6
+ (lambda (a b)
+ (< (string-to-number (aref (cadr a) 0))
+ (string-to-number (aref (cadr b) 0))))
+ :right-align t)
+ ("Trust" 5 t)
+ ("Warning" 0 nil)])
+ (tabulated-list-init-header))
+
+(defun org-lint--generate-reports (checkers)
+ "Run all CHECKERS in current buffer.
+Return an alist (ID [LINE TRUST DESCRIPTION]), suitable for
+`tabulated-list-printer'."
+ (save-excursion
+ (goto-char (point-min))
+ (let ((ast (org-element-parse-buffer))
+ (id 0)
+ (last-line 1)
+ (last-pos 1))
+ ;; Insert unique ID for each report. Replace buffer positions
+ ;; with line numbers.
+ (mapcar
+ (lambda (report)
+ (list
+ (incf id)
+ (apply #'vector
+ (cons
+ (progn
+ (goto-char (car report))
+ (beginning-of-line)
+ (prog1 (number-to-string
+ (incf last-line (count-lines last-pos (point))))
+ (setf last-pos (point))))
+ (cdr report)))))
+ ;; Insert trust level in generated reports. Also sort them by
+ ;; buffer position in order to optimize lines computation.
+ (sort (cl-mapcan
+ (lambda (c)
+ (let ((trust (symbol-name (org-lint-checker-trust c))))
+ (mapcar
+ (lambda (report) (list (car report) trust (nth 1 report)))
+ (save-excursion
+ (funcall (intern
+ (concat "org-lint-"
+ (symbol-name (org-lint-checker-name c))))
+ ast)))))
+ checkers)
+ #'car-less-than-car)))))
+
+(defvar org-lint--source-buffer nil
+ "Source buffer associated to current report buffer.")
+(make-variable-buffer-local 'org-lint--source-buffer)
+
+(defun org-lint--display-reports (source checkers)
+ "Display linting reports for buffer SOURCE.
+CHECKERS is the list of checkers used."
+ (let ((buffer (get-buffer-create "*Org Lint*")))
+ (with-current-buffer buffer
+ (org-lint--report-mode)
+ (setf org-lint--source-buffer source)
+ (setf tabulated-list-entries
+ (lambda ()
+ (with-current-buffer source
+ (org-lint--generate-reports checkers))))
+ (tabulated-list-print))
+ (pop-to-buffer buffer)))
+
+(defun org-lint--jump-to-source ()
+ "Move to source line that generated the report at point."
+ (interactive)
+ (let ((l (string-to-number (aref (tabulated-list-get-entry) 0))))
+ (switch-to-buffer-other-window org-lint--source-buffer)
+ (org-goto-line l)
+ (org-show-set-visibility 'local)
+ (recenter)))
+
+(defun org-lint--show-source ()
+ "Show source line that generated the report at point."
+ (interactive)
+ (let ((buffer (current-buffer))
+ (l (string-to-number (aref (tabulated-list-get-entry) 0))))
+ (switch-to-buffer-other-window org-lint--source-buffer)
+ (org-goto-line l)
+ (org-show-set-visibility 'local)
+ (recenter)
+ (switch-to-buffer-other-window buffer)))
+
+\f
+;;; Public function
+
+;;;###autoload
+(defun org-lint (&optional arg)
+ "Check current Org buffer for syntax mistakes.
+
+By default, run all checkers. With a single prefix ARG \
+\\[universal-argument],
+select one category of checkers only. With a double prefix
+\\[universal-argument] \\[universal-argument], select one precise \
+checker by its name.
+
+ARG can also be a list of checker names, as symbols, to run."
+ (interactive "P")
+ (unless (derived-mode-p 'org-mode) (user-error "Not in an Org buffer"))
+ (message "Org linting process starting...")
+ (org-lint--display-reports
+ (current-buffer)
+ (pcase arg
+ (`nil org-lint--checkers)
+ (`(4)
+ (let ((category
+ (completing-read
+ "Checker category: "
+ (mapcar #'org-lint-checker-categories org-lint--checkers)
+ nil t)))
+ (org-remove-if-not
+ (lambda (c) (assoc-string (org-lint-checker-categories c) category))
+ org-lint--checkers)))
+ (`(16)
+ (list
+ (let ((name (completing-read
+ "Checker name: "
+ (mapcar #'org-lint-checker-name org-lint--checkers)
+ nil t)))
+ (catch 'exit
+ (dolist (c org-lint--checkers)
+ (when (string= (org-lint-checker-name c) name)
+ (throw 'exit c)))))))
+ ((pred consp)
+ (org-remove-if-not (lambda (c) (memq (org-lint-checker-name c) arg))
+ org-lint--checkers))
+ (_ (user-error "Invalid argument `%S' for `org-lint'" arg))))
+ (message "Org linting process completed"))
+
+
+(provide 'org-lint)
+;;; org-lint.el ends here
--
2.3.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
2015-04-19 14:23 ` Rasmus
@ 2015-04-19 19:32 ` Marco Wahl
2015-04-20 10:42 ` Nicolas Goaziou
2015-04-20 2:15 ` Charles C. Berry
` (5 subsequent siblings)
7 siblings, 1 reply; 53+ messages in thread
From: Marco Wahl @ 2015-04-19 19:32 UTC (permalink / raw)
To: emacs-orgmode
Hi!
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> The following library implements linting for Org syntax. The sole public
> function is `org-lint', which see.
Great, thanks a lot. Already found some issues with some org-files.
> Results are displayed in a special "*Org Lint*" buffer with a dedicated
> major mode, derived from `tabulated-list-mode'. In addition to the usual
> key-bindings inherited from it, "C-j" displays problematic line reported
> under point and "RET" jumps to it.
Cool.
> Feedback welcome.
I think it's too much that org-lint tries to follow ssh links. This
slowed down the org-linting considerably in my case.
#v+
2278 low Link to non-existent local file "///ssh:root@127.0.0.1#2222:/etc/httpd/conf/httpd.conf"
#v-
My 2ct, Marco
--
http://www.wahlzone.de
GPG: 0x49010A040A3AE6F2
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
2015-04-19 14:23 ` Rasmus
2015-04-19 19:32 ` Marco Wahl
@ 2015-04-20 2:15 ` Charles C. Berry
2015-04-20 9:12 ` Nicolas Goaziou
2015-04-22 19:27 ` Nicolas Goaziou
` (4 subsequent siblings)
7 siblings, 1 reply; 53+ messages in thread
From: Charles C. Berry @ 2015-04-20 2:15 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: Org Mode List
On Sun, 19 Apr 2015, Nicolas Goaziou wrote:
> Hello,
>
> The following library implements linting for Org syntax. The sole public
> function is `org-lint', which see.
>
Nice!
Comments below.
> Internally, the library defines a new structure: `org-lint-checker',
> with the following slots:
>
[snip]
>
> Checks currently implemented are:
>
> - duplicates CUSTOM_ID properties
> - duplicate NAME values
> - duplicate targets
> - duplicate footnote definitions
> - orphaned affiliated keywords
This generates an orphaned keyword warning, but seems innocuous and is
what babel renders.
#+NAME: abc
#+BEGIN_SRC emacs-lisp
nil
#+END_SRC
#+RESULTS: abc
> - obsolete affiliated keywords
> - missing language in src blocks
> - NAME values with a colon
> - wrong header arguments in src blocks
IFF the header args are in the #+BEGIN_SRC line.
#+HEADER lines and header-arg properties are not screened AFAICS.
[snip]
Chuck
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-20 2:15 ` Charles C. Berry
@ 2015-04-20 9:12 ` Nicolas Goaziou
0 siblings, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-04-20 9:12 UTC (permalink / raw)
To: Charles C. Berry; +Cc: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 672 bytes --]
"Charles C. Berry" <ccberry@ucsd.edu> writes:
>> - orphaned affiliated keywords
>
> This generates an orphaned keyword warning, but seems innocuous and is
> what babel renders.
>
> #+NAME: abc
> #+BEGIN_SRC emacs-lisp
> nil #+END_SRC
>
> #+RESULTS: abc
Indeed, it is innocuous. It is meant to catch, e.g.,
#+CAPTION: my table
| table with a spurious newline above |
This check has a "low" trust level so false positive are OK.
>> - wrong header arguments in src blocks
>
> IFF the header args are in the #+BEGIN_SRC line.
>
> #+HEADER lines and header-arg properties are not screened AFAICS.
Indeed. Here's an update.
Thank you for the feedback.
Regards,
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Implement-Org-linting.patch --]
[-- Type: text/x-diff, Size: 27973 bytes --]
From 1b6b392f6e8e1bba68e07a36e7f9afc792e699a2 Mon Sep 17 00:00:00 2001
From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Date: Wed, 15 Apr 2015 22:24:15 +0200
Subject: [PATCH] Implement Org linting
* lisp/org-lint.el: New file.
---
lisp/org-lint.el | 768 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 768 insertions(+)
create mode 100644 lisp/org-lint.el
diff --git a/lisp/org-lint.el b/lisp/org-lint.el
new file mode 100644
index 0000000..c818ff1
--- /dev/null
+++ b/lisp/org-lint.el
@@ -0,0 +1,768 @@
+;;; org-lint.el --- Linting for Org documents -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015 Free Software Foundation
+
+;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
+;; Keywords: outlines, hypermedia, calendar, wp
+
+;; 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:
+
+;; This library implements linting for Org syntax. The sole public
+;; function is `org-lint', which see.
+
+;; Internally, the library defines a new structure:
+;; `org-lint-checker', with the following slots:
+
+;; - NAME: Unique check identifier, as a symbol. The check is done
+;; calling the function `org-lint-NAME' with one mandatory
+;; argument, the parse tree describing the current Org buffer.
+;; Such function calls are wrapped within a `save-excursion' and
+;; point is always at `point-min'. Its return value has to be an
+;; alist (POSITION MESSAGE) when POSITION refer to the buffer
+;; position of the error, as an integer, and MESSAGE is a strings
+;; describing the error.
+
+;; - DESCRIPTION: Summary about the check, as a string.
+
+;; - CATEGORIES: Categories relative to the check, as a list of
+;; symbol. They are used for filtering when calling `org-lint'.
+;; Checkers not explicitly associated to a category are collected
+;; in the `default' one.
+
+;; - TRUST: The trust level one can have in the check. It is either
+;; `low' or `high', depending on the heuristics implemented and
+;; the nature of the check. This has an indicative value only and
+;; is displayed along reports.
+
+;; All checks have to be listed in `org-lint--checkers'.
+
+;; Results are displayed in a special "*Org Lint*" buffer with
+;; a dedicated major mode, derived from `tabulated-list-mode'. In
+;; addition to the usual key-bindings inherited from it, "C-j"
+;; displays problematic line reported under point and "RET" jumps to
+;; it.
+
+;; Checks currently implemented are:
+
+;; - duplicates CUSTOM_ID properties
+;; - duplicate NAME values
+;; - duplicate targets
+;; - duplicate footnote definitions
+;; - orphaned affiliated keywords
+;; - obsolete affiliated keywords
+;; - missing language in src blocks
+;; - NAME values with a colon
+;; - wrong header arguments in src blocks
+;; - misuse of CATEGORY keyword
+;; - "coderef" links with unknown destination
+;; - "custom-id" links with unknown destination
+;; - "fuzzy" links with unknown destination
+;; - "id" links with unknown destination
+;; - links to non-existent local files
+;; - SETUPFILE keywords with non-existent file parameter
+;; - INCLUDE keywords with wrong link parameter
+;; - special properties in properties drawer
+;; - obsolete syntax for PROPERTIES drawers
+;; - missing definition for footnote references
+;; - missing reference for footnote definitions
+;; - non-footnote definitions in footnote section
+;; - probable invalid keywords
+;; - invalid blocks
+;; - probable incomplete drawers
+;; - obsolete QUOTE section
+
+\f
+;;; Code:
+
+(require 'cl-lib)
+(require 'org-element)
+(require 'ox)
+(require 'ob)
+
+\f
+;;; Checkers
+
+(cl-defstruct (org-lint-checker (:copier nil))
+ (name 'missing-checker-name)
+ (description "")
+ (categories '(default))
+ (trust 'high)) ; `low' or `high'
+
+(defun org-lint-missing-checker-name (_)
+ (error
+ "`A checker has no `:name' property. Please verify `org-lint--checkers'"))
+
+(defconst org-lint--checkers
+ (list
+ (make-org-lint-checker
+ :name 'duplicate-custom-id
+ :description "Report duplicates CUSTOM_ID properties"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'duplicate-name
+ :description "Report duplicate NAME values"
+ :categories '(babel link))
+ (make-org-lint-checker
+ :name 'duplicate-target
+ :description "Report duplicate targets"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'duplicate-footnote-definition
+ :description "Report duplicate footnote definitions"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'orphaned-affiliated-keywords
+ :description "Report orphaned affiliated keywords"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'obsolete-affiliated-keywords
+ :description "Report obsolete affiliated keywords"
+ :categories '(obsolete))
+ (make-org-lint-checker
+ :name 'missing-language-in-src-block
+ :description "Report missing language in src blocks"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'colon-in-name
+ :description "Report NAME values with a colon"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'wrong-header-argument
+ :description "Report wrong headers in src blocks, keywords and properties"
+ :categories '(babel))
+ (make-org-lint-checker
+ :name 'deprecated-category-setup
+ :description "Report misuse of CATEGORY keyword"
+ :categories '(obsolete))
+ (make-org-lint-checker
+ :name 'invalid-coderef-link
+ :description "Report \"coderef\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-custom-id-link
+ :description "Report \"custom-id\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-fuzzy-link
+ :description "Report \"fuzzy\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'invalid-id-link
+ :description "Report \"id\" links with unknown destination"
+ :categories '(link))
+ (make-org-lint-checker
+ :name 'link-to-local-file
+ :description "Report links to non-existent local files"
+ :categories '(link)
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'non-existent-setupfile-parameter
+ :description "Report SETUPFILE keywords with non-existent file parameter"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'wrong-include-link-parameter
+ :description "Report INCLUDE keywords with misleading link parameter"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'special-property-in-properties-drawer
+ :description "Report special properties in properties drawers"
+ :categories '(properties))
+ (make-org-lint-checker
+ :name 'obsolete-properties-drawer
+ :description "Report obsolete syntax for properties drawers"
+ :categories '(obsolete properties)
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'undefined-footnote-reference
+ :description "Report missing definition for footnote references"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'unreferenced-footnote-definition
+ :description "Report missing reference for footnote definitions"
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'extraneous-element-in-footnote-section
+ :description "Report non-footnote definitions in footnote section"
+ :trust 'high
+ :categories '(footnote))
+ (make-org-lint-checker
+ :name 'invalid-keyword-syntax
+ :description "Report probable invalid keywords"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'corrupted-block
+ :description "Report invalid blocks"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'incomplete-drawer
+ :description "Report probable incomplete drawers"
+ :trust 'low)
+ (make-org-lint-checker
+ :name 'quote-section
+ :description "Report obsolete QUOTE section"
+ :categories '(obsolete)
+ :trust 'low))
+ "List of all available checkers.")
+
+(defun org-lint-duplicate-custom-id (ast)
+ (org-element-map ast '(headline inlinetask)
+ (let (ids)
+ (lambda (e)
+ (let ((custom-id (org-element-property :CUSTOM_ID e)))
+ (cond
+ ((not custom-id) nil)
+ ((member custom-id ids)
+ (list (org-element-map e 'node-property
+ (lambda (p)
+ (and (eq (compare-strings
+ "CUSTOM_ID" nil nil
+ (org-element-property :key p) nil nil
+ t)
+ t)
+ (org-element-property :begin p)))
+ nil t)
+ (format "Duplicate CUSTOM_ID property \"%s\"" custom-id)))
+ (t (push custom-id ids) nil)))))))
+
+(defun org-lint-duplicate-name (ast)
+ (org-element-map ast org-element-all-elements
+ (let (names)
+ (lambda (e)
+ (let ((name (org-element-property :name e)))
+ (cond
+ ((not name) nil)
+ ((member name names)
+ (list (progn (goto-char (org-element-property :begin e))
+ (let ((case-fold-search t))
+ (re-search-forward
+ (concat "^[ \t]*#\\+NAME: +" (regexp-quote name)))
+ (match-beginning 0)))
+ (format "Duplicate NAME \"%s\"" name)))
+ (t (push name names) nil)))))))
+
+(defun org-lint-duplicate-target (ast)
+ (org-element-map ast 'target
+ (let (targets)
+ (lambda (o)
+ (let ((target (org-split-string (org-element-property :value o))))
+ (if (member target targets)
+ (list (org-element-property :begin o)
+ (format "Duplicate target \"%s\""
+ (org-element-property :value o)))
+ (push target targets)
+ nil))))))
+
+(defun org-lint-duplicate-footnote-definition (ast)
+ (org-element-map ast 'footnote-definition
+ (let (labels)
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (cond ((not label) nil)
+ ((member label labels)
+ (list (org-element-property :post-affiliated f)
+ (format "Duplicate footnote definition \"%s\"" label)))
+ (t (push label labels) nil)))))))
+
+(defun org-lint-orphaned-affiliated-keywords (ast)
+ (org-element-map ast 'keyword
+ (lambda (k)
+ (let ((key (org-element-property :key k)))
+ (and (member key org-element-affiliated-keywords)
+ (list (org-element-property :post-affiliated k)
+ (format "Orphaned affiliated keyword: \"%s\"" key)))))))
+
+(defun org-lint-obsolete-affiliated-keywords (_)
+ (let ((regexp (format "^[ \t]*#\\+%s:"
+ (regexp-opt '("DATA" "LABEL" "RESNAME" "SOURCE"
+ "SRCNAME" "TBLNAME" "RESULT" "HEADERS")
+ t)))
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((key (upcase (org-match-string-no-properties 1))))
+ (when (< (point)
+ (org-element-property :post-affiliated (org-element-at-point)))
+ (push
+ (list (line-beginning-position)
+ (format
+ "Obsolete affiliated keyword: \"%s\". Use \"%s\" instead"
+ key
+ (pcase key
+ ("HEADERS" "HEADER")
+ ("RESULT" "RESULTS")
+ (_ "NAME"))))
+ reports))))
+ reports))
+
+(defun org-lint-missing-language-in-src-block (ast)
+ (org-element-map ast 'src-block
+ (lambda (b)
+ (unless (org-element-property :language b)
+ (list (org-element-property :post-affiliated b)
+ "Missing language in source block")))))
+
+(defun org-lint-deprecated-category-setup (ast)
+ (org-element-map ast 'keyword
+ (let (category-flag)
+ (lambda (k)
+ (cond
+ ((not (string= (org-element-property :key k) "CATEGORY")) nil)
+ (category-flag
+ (list (org-element-property :post-affiliated k)
+ "Spurious CATEGORY keyword. Set :CATEGORY: property instead"))
+ (t (setf category-flag t) nil))))))
+
+(defun org-lint-invalid-coderef-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (let ((ref (org-element-property :path link)))
+ (and (equal (org-element-property :type link) "coderef")
+ (not (ignore-errors (org-export-resolve-coderef ref info)))
+ (list (org-element-property :begin link)
+ (format "Unknown coderef \"%s\"" ref))))))))
+
+(defun org-lint-invalid-custom-id-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (and (equal (org-element-property :type link) "custom-id")
+ (not (ignore-errors (org-export-resolve-id-link link info)))
+ (list (org-element-property :begin link)
+ (format "Unknown custom ID \"%s\""
+ (org-element-property :path link))))))))
+
+(defun org-lint-invalid-fuzzy-link (ast)
+ (let ((info (list :parse-tree ast)))
+ (org-element-map ast 'link
+ (lambda (link)
+ (and (equal (org-element-property :type link) "fuzzy")
+ (not (ignore-errors (org-export-resolve-fuzzy-link link info)))
+ (list (org-element-property :begin link)
+ (format "Unknown fuzzy location \"%s\""
+ (let ((path (org-element-property :path link)))
+ (if (string-prefix-p "*" path)
+ (substring path 1)
+ path)))))))))
+
+(defun org-lint-invalid-id-link (ast)
+ (org-element-map ast 'link
+ (lambda (link)
+ (let ((id (org-element-property :path link)))
+ (and (equal (org-element-property :type link) "id")
+ (not (org-id-find id))
+ (list (org-element-property :begin link)
+ (format "Unknown ID \"%s\"" id)))))))
+
+(defun org-lint-special-property-in-properties-drawer (ast)
+ (org-element-map ast 'node-property
+ (lambda (p)
+ (let ((key (org-element-property :key p)))
+ (and (member-ignore-case key org-special-properties)
+ (list (org-element-property :begin p)
+ (format
+ "Special property \"%s\" found in a properties drawer"
+ key)))))))
+
+(defun org-lint-obsolete-properties-drawer (ast)
+ (org-element-map ast 'drawer
+ (lambda (d)
+ (when (equal (org-element-property :drawer-name d) "PROPERTIES")
+ (let ((section (org-element-lineage d '(section))))
+ (unless (org-element-map section 'property-drawer #'identity nil t)
+ (list (org-element-property :post-affiliated d)
+ (if (save-excursion
+ (goto-char (org-element-property :post-affiliated d))
+ (forward-line -1)
+ (or (org-at-heading-p) (org-at-planning-p)))
+ "Incorrect contents for PROPERTIES drawer"
+ "Incorrect location for PROPERTIES drawer"))))))))
+
+(defun org-lint-link-to-local-file (ast)
+ (org-element-map ast 'link
+ (lambda (l)
+ (when (equal (org-element-property :type l) "file")
+ (let ((file (org-element-property :path l)))
+ (and (not (file-remote-p file))
+ (not (file-exists-p file))
+ (list (org-element-property :begin l)
+ (format "Link to non-existent local file \"%s\""
+ file))))))))
+
+(defun org-lint-non-existent-setupfile-parameter (ast)
+ (org-element-map ast 'keyword
+ (lambda (k)
+ (when (equal (org-element-property :key k) "SETUPFILE")
+ (let ((file (org-remove-double-quotes
+ (org-element-property :value k))))
+ (and (not (file-remote-p file))
+ (not (file-exists-p file))
+ (list (org-element-property :begin k)
+ (format "Non-existent setup file \"%s\"" file))))))))
+
+(defun org-lint-wrong-include-link-parameter (ast)
+ (org-element-map ast 'keyword
+ (lambda (k)
+ (when (equal (org-element-property :key k) "INCLUDE")
+ (let* ((value (org-element-property :value k))
+ (path
+ (and (string-match "^\\(\".+\"\\|\\S-+\\)[ \t]*" value)
+ (save-match-data
+ (org-remove-double-quotes (match-string 1 value))))))
+ (if (not path)
+ (list (org-element-property :post-affiliated k)
+ "Missing location argument in INCLUDE keyword")
+ (let* ((file (org-string-nw-p
+ (if (string-match "::\\(.*\\)\\'" path)
+ (substring path 0 (match-beginning 0))
+ path)))
+ (search (and (not (equal file path))
+ (org-string-nw-p (match-string 1 path)))))
+ (if (and file
+ (not (file-remote-p file))
+ (not (file-exists-p file)))
+ (list (org-element-property :post-affiliated k)
+ "Non-existent file argument in INCLUDE keyword")
+ (let* ((visiting (if file (find-buffer-visiting file)
+ (current-buffer)))
+ (buffer (or visiting (find-file-noselect file))))
+ (unwind-protect
+ (with-current-buffer buffer
+ (when (and search
+ (not
+ (ignore-errors
+ (let ((org-link-search-inhibit-query t))
+ (org-link-search search nil nil t)))))
+ (list
+ (org-element-property :post-affiliated k)
+ (format
+ "Invalid search part \"%s\" in INCLUDE keyword"
+ search))))
+ (unless visiting (kill-buffer buffer))))))))))))
+
+(defun org-lint-undefined-footnote-reference (ast)
+ (let ((definitions (org-element-map ast 'footnote-definition
+ (lambda (f) (org-element-property :label f)))))
+ (org-element-map ast 'footnote-reference
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (and label
+ (not (member label definitions))
+ (list (org-element-property :begin f)
+ (format "Missing definition for footnote [%s]"
+ label))))))))
+
+(defun org-lint-unreferenced-footnote-definition (ast)
+ (let ((references (org-element-map ast 'footnote-reference
+ (lambda (f) (org-element-property :label f)))))
+ (org-element-map ast 'footnote-definition
+ (lambda (f)
+ (let ((label (org-element-property :label f)))
+ (and label
+ (not (member label references))
+ (list (org-element-property :post-affiliated f)
+ (format "No reference for footnote definition [%s]"
+ label))))))))
+
+(defun org-lint-colon-in-name (ast)
+ (org-element-map ast org-element-all-elements
+ (lambda (e)
+ (let ((name (org-element-property :name e)))
+ (and name
+ (org-string-match-p ":" name)
+ (list (progn
+ (goto-char (org-element-property :begin e))
+ (let ((case-fold-search t))
+ (re-search-forward
+ (concat "^[ \t]*#\\+NAME: +" (regexp-quote name)))
+ (match-beginning 0)))
+ (format
+ "Name \"%s\" contains a colon; Babel cannot use it as input"
+ name)))))))
+
+(defun org-lint-incomplete-drawer (_)
+ (let (reports)
+ (while (re-search-forward org-drawer-regexp nil t)
+ (let ((name (org-trim (org-match-string-no-properties 0)))
+ (element (org-element-at-point)))
+ (pcase (org-element-type element)
+ (`(drawer property-drawer)
+ (goto-char (org-element-property :end element))
+ nil)
+ (`paragraph
+ (push (list (line-beginning-position)
+ (format "Possible incomplete drawer \"%s\"" name))
+ reports))
+ (_ nil))))
+ reports))
+
+(defun org-lint-corrupted-block (_)
+ (let ((case-fold-search t)
+ (regexp "^[ \t]*#\\+\\(BEGIN\\|END\\)\\(?::\\|_[^[:space:]]*\\)?[ \t]*")
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((name (org-trim (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position)))))
+ (cond
+ ((and (string-prefix-p "END" (match-string 1) t)
+ (not (eolp)))
+ (push (list (line-beginning-position)
+ (format "Invalid block closing line \"%s\"" name))
+ reports))
+ ((eq (org-element-type (org-element-at-point)) 'paragraph)
+ (push (list (line-beginning-position)
+ (format "Possible incomplete block \"%s\""
+ name))
+ reports)))))
+ reports))
+
+(defun org-lint-invalid-keyword-syntax (_)
+ (let ((regexp "^[ \t]*\\(#\\+[^[:space:]:]*\\)\\(?:[[:space:]]\\|$\\)")
+ reports)
+ (while (re-search-forward regexp nil t)
+ (let ((name (org-match-string-no-properties 1)))
+ (unless (or (string-prefix-p "#+BEGIN" name t)
+ (string-prefix-p "#+END" name t))
+ (push (list (match-beginning 0)
+ (format "Possible missing colon in keyword \"%s\"" name))
+ reports))))
+ reports))
+
+(defun org-lint-extraneous-element-in-footnote-section (ast)
+ (org-element-map ast 'headline
+ (lambda (h)
+ (and (org-element-property :footnote-section-p h)
+ (org-element-map (org-element-contents h)
+ (org-remove-if
+ (lambda (e)
+ (memq e '(comment comment-block footnote-definition
+ property-drawer section)))
+ org-element-all-elements)
+ (lambda (e)
+ (not (and (eq (org-element-type e) 'headline)
+ (org-element-property :commentedp e))))
+ nil t '(footnote-definition property-drawer))
+ (list (org-element-property :begin h)
+ "Extraneous elements in footnote section")))))
+
+(defun org-lint-quote-section (ast)
+ (org-element-map ast '(headline inlinetask)
+ (lambda (h)
+ (let ((title (org-element-property :raw-value h)))
+ (and (or (string-prefix-p "QUOTE " title)
+ (string-prefix-p (concat org-comment-string " QUOTE ") title))
+ (list (org-element-property :begin h)
+ "Deprecated QUOTE section"))))))
+
+(defun org-lint-wrong-header-argument (ast)
+ (let* ((reports)
+ (verify
+ (lambda (datum lang headers)
+ (let ((allowed
+ (append
+ org-babel-header-arg-names
+ (and lang
+ (let ((v (intern
+ (concat "org-babel-header-args:" lang))))
+ (and (boundp v)
+ (mapcar #'car (symbol-value v))))))))
+ (dolist (header headers)
+ (let ((h (substring (symbol-name (car header)) 1)))
+ (unless (assoc-string h allowed)
+ (push (list (org-element-property :post-affiliated datum)
+ (format "Unknown header argument \"%s\"" h))
+ reports))))))))
+ (org-element-map ast '(keyword node-property src-block)
+ (lambda (datum)
+ (pcase (org-element-type datum)
+ (`keyword
+ (when (string= (org-element-property :key datum) "PROPERTY")
+ (let ((value (org-element-property :value datum)))
+ (when (string-match "\\`header-args\\(?::\\(\\S-+\\)\\)? *"
+ value)
+ (funcall verify
+ datum
+ (match-string 1 value)
+ (org-babel-parse-header-arguments
+ (substring value (match-end 0))))))))
+ (`node-property
+ (let ((key (org-element-property :key datum)))
+ (when (let ((case-fold-search t))
+ (string-match "\\`HEADER-ARGS\\(?::\\(\\S-+\\)\\)?" key))
+ (funcall verify
+ datum
+ (match-string 1 key)
+ (org-babel-parse-header-arguments
+ (org-element-property :value datum))))))
+ (`src-block
+ (funcall verify
+ datum
+ (org-element-property :language datum)
+ (cl-mapcan #'org-babel-parse-header-arguments
+ (cons (org-element-property :parameters datum)
+ (org-element-property :header datum))))))))
+ reports))
+
+\f
+;;; Reports UI
+
+(defvar org-lint--report-mode-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map tabulated-list-mode-map)
+ (define-key map (kbd "RET") 'org-lint--jump-to-source)
+ (define-key map (kbd "C-j") 'org-lint--show-source)
+ map)
+ "Local keymap for `org-lint--report-mode' buffers.")
+
+(define-derived-mode org-lint--report-mode tabulated-list-mode "OrgLint"
+ "Major mode used to display reports emitted during linting.
+\\<package-menu-mode-map>"
+ (setf tabulated-list-format
+ `[("Line" 6
+ (lambda (a b)
+ (< (string-to-number (aref (cadr a) 0))
+ (string-to-number (aref (cadr b) 0))))
+ :right-align t)
+ ("Trust" 5 t)
+ ("Warning" 0 nil)])
+ (tabulated-list-init-header))
+
+(defun org-lint--generate-reports (checkers)
+ "Run all CHECKERS in current buffer.
+Return an alist (ID [LINE TRUST DESCRIPTION]), suitable for
+`tabulated-list-printer'."
+ (save-excursion
+ (goto-char (point-min))
+ (let ((ast (org-element-parse-buffer))
+ (id 0)
+ (last-line 1)
+ (last-pos 1))
+ ;; Insert unique ID for each report. Replace buffer positions
+ ;; with line numbers.
+ (mapcar
+ (lambda (report)
+ (list
+ (incf id)
+ (apply #'vector
+ (cons
+ (progn
+ (goto-char (car report))
+ (beginning-of-line)
+ (prog1 (number-to-string
+ (incf last-line (count-lines last-pos (point))))
+ (setf last-pos (point))))
+ (cdr report)))))
+ ;; Insert trust level in generated reports. Also sort them by
+ ;; buffer position in order to optimize lines computation.
+ (sort (cl-mapcan
+ (lambda (c)
+ (let ((trust (symbol-name (org-lint-checker-trust c))))
+ (mapcar
+ (lambda (report) (list (car report) trust (nth 1 report)))
+ (save-excursion
+ (funcall (intern
+ (concat "org-lint-"
+ (symbol-name (org-lint-checker-name c))))
+ ast)))))
+ checkers)
+ #'car-less-than-car)))))
+
+(defvar org-lint--source-buffer nil
+ "Source buffer associated to current report buffer.")
+(make-variable-buffer-local 'org-lint--source-buffer)
+
+(defun org-lint--display-reports (source checkers)
+ "Display linting reports for buffer SOURCE.
+CHECKERS is the list of checkers used."
+ (let ((buffer (get-buffer-create "*Org Lint*")))
+ (with-current-buffer buffer
+ (org-lint--report-mode)
+ (setf org-lint--source-buffer source)
+ (setf tabulated-list-entries
+ (lambda ()
+ (with-current-buffer source
+ (org-lint--generate-reports checkers))))
+ (tabulated-list-print))
+ (pop-to-buffer buffer)))
+
+(defun org-lint--jump-to-source ()
+ "Move to source line that generated the report at point."
+ (interactive)
+ (let ((l (string-to-number (aref (tabulated-list-get-entry) 0))))
+ (switch-to-buffer-other-window org-lint--source-buffer)
+ (org-goto-line l)
+ (org-show-set-visibility 'local)
+ (recenter)))
+
+(defun org-lint--show-source ()
+ "Show source line that generated the report at point."
+ (interactive)
+ (let ((buffer (current-buffer))
+ (l (string-to-number (aref (tabulated-list-get-entry) 0))))
+ (switch-to-buffer-other-window org-lint--source-buffer)
+ (org-goto-line l)
+ (org-show-set-visibility 'local)
+ (recenter)
+ (switch-to-buffer-other-window buffer)))
+
+\f
+;;; Public function
+
+;;;###autoload
+(defun org-lint (&optional arg)
+ "Check current Org buffer for syntax mistakes.
+
+By default, run all checkers. With a single prefix ARG \
+\\[universal-argument],
+select one category of checkers only. With a double prefix
+\\[universal-argument] \\[universal-argument], select one precise \
+checker by its name.
+
+ARG can also be a list of checker names, as symbols, to run."
+ (interactive "P")
+ (unless (derived-mode-p 'org-mode) (user-error "Not in an Org buffer"))
+ (message "Org linting process starting...")
+ (org-lint--display-reports
+ (current-buffer)
+ (pcase arg
+ (`nil org-lint--checkers)
+ (`(4)
+ (let ((category
+ (completing-read
+ "Checker category: "
+ (mapcar #'org-lint-checker-categories org-lint--checkers)
+ nil t)))
+ (org-remove-if-not
+ (lambda (c) (assoc-string (org-lint-checker-categories c) category))
+ org-lint--checkers)))
+ (`(16)
+ (list
+ (let ((name (completing-read
+ "Checker name: "
+ (mapcar #'org-lint-checker-name org-lint--checkers)
+ nil t)))
+ (catch 'exit
+ (dolist (c org-lint--checkers)
+ (when (string= (org-lint-checker-name c) name)
+ (throw 'exit c)))))))
+ ((pred consp)
+ (org-remove-if-not (lambda (c) (memq (org-lint-checker-name c) arg))
+ org-lint--checkers))
+ (_ (user-error "Invalid argument `%S' for `org-lint'" arg))))
+ (message "Org linting process completed"))
+
+
+(provide 'org-lint)
+;;; org-lint.el ends here
--
2.3.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 19:32 ` Marco Wahl
@ 2015-04-20 10:42 ` Nicolas Goaziou
0 siblings, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-04-20 10:42 UTC (permalink / raw)
To: Marco Wahl; +Cc: emacs-orgmode
Marco Wahl <marcowahlsoft@gmail.com> writes:
> I think it's too much that org-lint tries to follow ssh links.
It doesn't follow remote paths.
> 2278 low Link to non-existent local file "///ssh:root@127.0.0.1#2222:/etc/httpd/conf/httpd.conf"
^^^^^ ^^^
There's a bug in the parser, which doesn't know how to handle
"/ssh:root@127.0.0.1#2222:/etc/httpd/conf/httpd.conf".
It prefixes it with "//", turning it into
"///ssh:root@127.0.0.1#2222:/etc/httpd/conf/httpd.conf". Then `org-lint'
thinks it's a local file.
The problem should be fixed in master, so you need to update Org.
Thanks for the feedback.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
` (2 preceding siblings ...)
2015-04-20 2:15 ` Charles C. Berry
@ 2015-04-22 19:27 ` Nicolas Goaziou
2015-04-22 19:31 ` Sebastien Vauban
` (2 more replies)
2015-04-27 15:22 ` Doug Lewan
` (3 subsequent siblings)
7 siblings, 3 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-04-22 19:27 UTC (permalink / raw)
To: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 190 bytes --]
Here's another update. I added a few more tests.
If there's no more bug report or feedback, I'll simply put it in
a "wip-lint" branch until Org 8.4 starts its development cycle.
Regards,
[-- Attachment #2: org-lint.el --]
[-- Type: application/emacs-lisp, Size: 33790 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-22 19:27 ` Nicolas Goaziou
@ 2015-04-22 19:31 ` Sebastien Vauban
2015-04-22 19:40 ` Nicolas Goaziou
2015-04-23 10:47 ` Eric Abrahamsen
2015-04-23 16:25 ` Sebastien Vauban
2 siblings, 1 reply; 53+ messages in thread
From: Sebastien Vauban @ 2015-04-22 19:31 UTC (permalink / raw)
To: emacs-orgmode-mXXj517/zsQ
Hello Nicolas,
Nicolas Goaziou wrote:
> Here's another update. I added a few more tests.
>
> If there's no more bug report or feedback, I'll simply put it in
> a "wip-lint" branch until Org 8.4 starts its development cycle.
I'd like to enforce org-lint on all my Org docs, either in a find-file
hook or before export, for example.
Can't you put it in master as well?
Best regards,
Seb
--
Sebastien Vauban
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-22 19:31 ` Sebastien Vauban
@ 2015-04-22 19:40 ` Nicolas Goaziou
0 siblings, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-04-22 19:40 UTC (permalink / raw)
To: Sebastien Vauban; +Cc: public-emacs-orgmode-mXXj517/zsQ
Sebastien Vauban <sva-news-D0wtAvR13HarG/iDocfnWg@public.gmane.org>
writes:
> I'd like to enforce org-lint on all my Org docs, either in a find-file
> hook or before export, for example.
>
> Can't you put it in master as well?
No, I can't.
As explained in the original post, "org-lint.el" requires at least Emacs
24.3 (lexical binding, pcase, tabulated-list-mode...) whereas Org 8.3 is
expected to be Emacs 23 compatible.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-22 19:27 ` Nicolas Goaziou
2015-04-22 19:31 ` Sebastien Vauban
@ 2015-04-23 10:47 ` Eric Abrahamsen
2015-04-23 16:25 ` Sebastien Vauban
2 siblings, 0 replies; 53+ messages in thread
From: Eric Abrahamsen @ 2015-04-23 10:47 UTC (permalink / raw)
To: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Here's another update. I added a few more tests.
>
> If there's no more bug report or feedback, I'll simply put it in
> a "wip-lint" branch until Org 8.4 starts its development cycle.
This is handy! No bugs to report.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-22 19:27 ` Nicolas Goaziou
2015-04-22 19:31 ` Sebastien Vauban
2015-04-23 10:47 ` Eric Abrahamsen
@ 2015-04-23 16:25 ` Sebastien Vauban
2015-04-26 12:50 ` Nicolas Goaziou
2 siblings, 1 reply; 53+ messages in thread
From: Sebastien Vauban @ 2015-04-23 16:25 UTC (permalink / raw)
To: emacs-orgmode-mXXj517/zsQ
Nicolas Goaziou wrote:
> Here's another update. I added a few more tests.
>
> If there's no more bug report or feedback, I'll simply put it in
> a "wip-lint" branch until Org 8.4 starts its development cycle.
Could `org-lint' return a success/fail indication, so that we could
write something along in an export hook:
--8<---------------cut here---------------start------------->8---
(if (org-lint)
... continue with export ...
... stop with message or display the lint buffer ...)
--8<---------------cut here---------------end--------------->8---
As well, could the buffer be hidden (or killed) if it's empty?
Best regards,
Seb
--
Sebastien Vauban
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-23 16:25 ` Sebastien Vauban
@ 2015-04-26 12:50 ` Nicolas Goaziou
0 siblings, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-04-26 12:50 UTC (permalink / raw)
To: Sebastien Vauban; +Cc: public-emacs-orgmode-mXXj517/zsQ
Sebastien Vauban <sva-news-D0wtAvR13HarG/iDocfnWg@public.gmane.org>
writes:
> Could `org-lint' return a success/fail indication, so that we could
> write something along in an export hook:
>
> (if (org-lint)
> ... continue with export ...
> ... stop with message or display the lint buffer ...)
>
> As well, could the buffer be hidden (or killed) if it's empty?
When called non-interactively `org-lint' returns the reports, as an
alist or nil, so it can be used as a predicate.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
` (3 preceding siblings ...)
2015-04-22 19:27 ` Nicolas Goaziou
@ 2015-04-27 15:22 ` Doug Lewan
2015-05-19 11:54 ` Andreas Leha
` (2 subsequent siblings)
7 siblings, 0 replies; 53+ messages in thread
From: Doug Lewan @ 2015-04-27 15:22 UTC (permalink / raw)
To: Nicolas Goaziou, Org Mode List
> -----Original Message-----
> On
> Behalf Of Nicolas Goaziou
> Sent: Sunday, 2015 April 19 09:32
> To: Org Mode List
> Subject: [O] [RFC] Org linting library
>
> Hello,
>
> The following library implements linting for Org syntax. The sole
> public
> function is `org-lint', which see.
> Nicolas Goaziou
> 0x80A93738
[Doug Lewan]
Very cool. Thank you.
--
,Doug
Douglas Lewan
Shubert Ticketing
(201) 489-8600 ext 224 or ext 4335
The human brain is the most complex thing known to man, according to the human brain.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
` (4 preceding siblings ...)
2015-04-27 15:22 ` Doug Lewan
@ 2015-05-19 11:54 ` Andreas Leha
2015-05-19 13:39 ` Nicolas Goaziou
2015-05-19 13:32 ` Rainer M Krug
2015-06-05 10:51 ` Rainer M Krug
7 siblings, 1 reply; 53+ messages in thread
From: Andreas Leha @ 2015-05-19 11:54 UTC (permalink / raw)
To: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Hello,
>
> The following library implements linting for Org syntax. The sole public
> function is `org-lint', which see.
>
> Internally, the library defines a new structure: `org-lint-checker',
> with the following slots:
>
> - NAME: Unique check identifier, as a symbol. The check is done
> calling the function `org-lint-NAME' with one mandatory argument,
> the parse tree describing the current Org buffer. Such function
> calls are wrapped within a `save-excursion' and point is always at
> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
> when POSITION refer to the buffer position of the error, as an
> integer, and MESSAGE is a strings describing the error.
>
> - DESCRIPTION: Summary about the check, as a string.
>
> - CATEGORIES: Categories relative to the check, as a list of symbol.
> They are used for filtering when calling `org-lint'. Checkers not
> explicitly associated to a category are collected in the `default'
> one.
>
> - TRUST: The trust level one can have in the check. It is either `low'
> or `high', depending on the heuristics implemented and the nature of
> the check. This has an indicative value only and is displayed along
> reports.
>
> All checks have to be listed in `org-lint--checkers'.
>
> Results are displayed in a special "*Org Lint*" buffer with a dedicated
> major mode, derived from `tabulated-list-mode'. In addition to the usual
> key-bindings inherited from it, "C-j" displays problematic line reported
> under point and "RET" jumps to it.
>
> Checks currently implemented are:
>
> - duplicates CUSTOM_ID properties
> - duplicate NAME values
> - duplicate targets
> - duplicate footnote definitions
> - orphaned affiliated keywords
> - obsolete affiliated keywords
> - missing language in src blocks
> - NAME values with a colon
> - wrong header arguments in src blocks
> - misuse of CATEGORY keyword
> - "coderef" links with unknown destination
> - "custom-id" links with unknown destination
> - "fuzzy" links with unknown destination
> - "id" links with unknown destination
> - links to non-existent local files
> - special properties in properties drawer
> - obsolete syntax for PROPERTIES drawers
> - missing definition for footnote references
> - missing reference for footnote definitions
> - non-footnote definitions in footnote section
> - probable invalid keywords
> - invalid blocks
> - probable incomplete drawers
> - obsolete QUOTE section
>
> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
> useful enough.
>
> Feedback welcome.
>
>
> Regards,
Hi Nicolas,
I have finally made some time to test this. I get some
unexpected warnings:
79 low Unknown value "myfile.R" for header ":tangle"
192 low Unknown value "none" for header ":results"
22985 low Unknown value "never-export" for header ":eval"
Thanks for this very useful tool!
Thanks,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
` (5 preceding siblings ...)
2015-05-19 11:54 ` Andreas Leha
@ 2015-05-19 13:32 ` Rainer M Krug
2015-05-19 13:43 ` Andreas Leha
2015-05-19 13:47 ` Nicolas Goaziou
2015-06-05 10:51 ` Rainer M Krug
7 siblings, 2 replies; 53+ messages in thread
From: Rainer M Krug @ 2015-05-19 13:32 UTC (permalink / raw)
To: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 3477 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Hello,
>
> The following library implements linting for Org syntax. The sole public
> function is `org-lint', which see.
>
> Internally, the library defines a new structure: `org-lint-checker',
> with the following slots:
>
> - NAME: Unique check identifier, as a symbol. The check is done
> calling the function `org-lint-NAME' with one mandatory argument,
> the parse tree describing the current Org buffer. Such function
> calls are wrapped within a `save-excursion' and point is always at
> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
> when POSITION refer to the buffer position of the error, as an
> integer, and MESSAGE is a strings describing the error.
>
> - DESCRIPTION: Summary about the check, as a string.
>
> - CATEGORIES: Categories relative to the check, as a list of symbol.
> They are used for filtering when calling `org-lint'. Checkers not
> explicitly associated to a category are collected in the `default'
> one.
>
> - TRUST: The trust level one can have in the check. It is either `low'
> or `high', depending on the heuristics implemented and the nature of
> the check. This has an indicative value only and is displayed along
> reports.
>
> All checks have to be listed in `org-lint--checkers'.
>
> Results are displayed in a special "*Org Lint*" buffer with a dedicated
> major mode, derived from `tabulated-list-mode'. In addition to the usual
> key-bindings inherited from it, "C-j" displays problematic line reported
> under point and "RET" jumps to it.
>
> Checks currently implemented are:
>
> - duplicates CUSTOM_ID properties
> - duplicate NAME values
> - duplicate targets
> - duplicate footnote definitions
> - orphaned affiliated keywords
> - obsolete affiliated keywords
> - missing language in src blocks
> - NAME values with a colon
> - wrong header arguments in src blocks
> - misuse of CATEGORY keyword
> - "coderef" links with unknown destination
> - "custom-id" links with unknown destination
> - "fuzzy" links with unknown destination
> - "id" links with unknown destination
> - links to non-existent local files
> - special properties in properties drawer
> - obsolete syntax for PROPERTIES drawers
> - missing definition for footnote references
> - missing reference for footnote definitions
> - non-footnote definitions in footnote section
> - probable invalid keywords
> - invalid blocks
> - probable incomplete drawers
> - obsolete QUOTE section
>
> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
> useful enough.
>
This sounds very interesting and I would like to try it out. I
understand that it can't be put into master, but could it be put into a
branch?
This would make testing a bit easier.
Thanks,
Rainer
> Feedback welcome.
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 11:54 ` Andreas Leha
@ 2015-05-19 13:39 ` Nicolas Goaziou
2015-05-19 14:54 ` Andreas Leha
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-19 13:39 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode
Hello,
Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
> I have finally made some time to test this. I get some
> unexpected warnings:
>
> 79 low Unknown value "myfile.R" for header ":tangle"
> 192 low Unknown value "none" for header ":results"
Make sure you rebased the wip-lint branch on top of master.
> 22985 low Unknown value "never-export" for header ":eval"
I added it to allowed value. You need to update Org.
> Thanks for this very useful tool!
Thanks for the feedback.
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 13:32 ` Rainer M Krug
@ 2015-05-19 13:43 ` Andreas Leha
2015-05-20 15:01 ` Rainer M Krug
2015-05-19 13:47 ` Nicolas Goaziou
1 sibling, 1 reply; 53+ messages in thread
From: Andreas Leha @ 2015-05-19 13:43 UTC (permalink / raw)
To: emacs-orgmode
Hi Rainer,
Rainer M Krug <Rainer@krugs.de> writes:
> Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>
>> Hello,
>>
>> The following library implements linting for Org syntax. The sole public
>> function is `org-lint', which see.
>>
>> Internally, the library defines a new structure: `org-lint-checker',
>> with the following slots:
>>
>> - NAME: Unique check identifier, as a symbol. The check is done
>> calling the function `org-lint-NAME' with one mandatory argument,
>> the parse tree describing the current Org buffer. Such function
>> calls are wrapped within a `save-excursion' and point is always at
>> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
>> when POSITION refer to the buffer position of the error, as an
>> integer, and MESSAGE is a strings describing the error.
>>
>> - DESCRIPTION: Summary about the check, as a string.
>>
>> - CATEGORIES: Categories relative to the check, as a list of symbol.
>> They are used for filtering when calling `org-lint'. Checkers not
>> explicitly associated to a category are collected in the `default'
>> one.
>>
>> - TRUST: The trust level one can have in the check. It is either `low'
>> or `high', depending on the heuristics implemented and the nature of
>> the check. This has an indicative value only and is displayed along
>> reports.
>>
>> All checks have to be listed in `org-lint--checkers'.
>>
>> Results are displayed in a special "*Org Lint*" buffer with a dedicated
>> major mode, derived from `tabulated-list-mode'. In addition to the usual
>> key-bindings inherited from it, "C-j" displays problematic line reported
>> under point and "RET" jumps to it.
>>
>> Checks currently implemented are:
>>
>> - duplicates CUSTOM_ID properties
>> - duplicate NAME values
>> - duplicate targets
>> - duplicate footnote definitions
>> - orphaned affiliated keywords
>> - obsolete affiliated keywords
>> - missing language in src blocks
>> - NAME values with a colon
>> - wrong header arguments in src blocks
>> - misuse of CATEGORY keyword
>> - "coderef" links with unknown destination
>> - "custom-id" links with unknown destination
>> - "fuzzy" links with unknown destination
>> - "id" links with unknown destination
>> - links to non-existent local files
>> - special properties in properties drawer
>> - obsolete syntax for PROPERTIES drawers
>> - missing definition for footnote references
>> - missing reference for footnote definitions
>> - non-footnote definitions in footnote section
>> - probable invalid keywords
>> - invalid blocks
>> - probable incomplete drawers
>> - obsolete QUOTE section
>>
>> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
>> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
>> useful enough.
>>
>
> This sounds very interesting and I would like to try it out. I
> understand that it can't be put into master, but could it be put into a
> branch?
>
> This would make testing a bit easier.
>
It is. The branch is called `wip-lint'.
Regards,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 13:32 ` Rainer M Krug
2015-05-19 13:43 ` Andreas Leha
@ 2015-05-19 13:47 ` Nicolas Goaziou
1 sibling, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-19 13:47 UTC (permalink / raw)
To: Rainer M Krug; +Cc: Org Mode List
Rainer M Krug <Rainer@krugs.de> writes:
> This sounds very interesting and I would like to try it out. I
> understand that it can't be put into master, but could it be put into a
> branch?
It already lives in "wip-lint" branch.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 13:39 ` Nicolas Goaziou
@ 2015-05-19 14:54 ` Andreas Leha
2015-05-19 19:09 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Andreas Leha @ 2015-05-19 14:54 UTC (permalink / raw)
To: emacs-orgmode
Hi Nicolas,
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>> I have finally made some time to test this. I get some
>> unexpected warnings:
>>
>> 79 low Unknown value "myfile.R" for header ":tangle"
>> 192 low Unknown value "none" for header ":results"
>
> Make sure you rebased the wip-lint branch on top of master.
>
>> 22985 low Unknown value "never-export" for header ":eval"
>
> I added it to allowed value. You need to update Org.
>
I just pulled and rebased again. The "never-export" issue is
gone, indeed. The others are still there. What am I missing
here?
Thanks,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 14:54 ` Andreas Leha
@ 2015-05-19 19:09 ` Nicolas Goaziou
2015-05-19 20:02 ` Andreas Leha
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-19 19:09 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode
Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
> I just pulled and rebased again. The "never-export" issue is
> gone, indeed. The others are still there. What am I missing
> here?
Nothing. I overlooked a typo. It should be fixed in wip-lint.
Thank you.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 19:09 ` Nicolas Goaziou
@ 2015-05-19 20:02 ` Andreas Leha
2015-05-19 21:03 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Andreas Leha @ 2015-05-19 20:02 UTC (permalink / raw)
To: emacs-orgmode
Hi Nicolas,
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
>
>> I just pulled and rebased again. The "never-export" issue is
>> gone, indeed. The others are still there. What am I missing
>> here?
>
> Nothing. I overlooked a typo. It should be fixed in wip-lint.
Thanks. Now the :tangle header argument does not produce a
warning.
But I still get
--8<---------------cut here---------------start------------->8---
191 low Unknown value "none" for header ":results"
--8<---------------cut here---------------end--------------->8---
Ahh, and one more thing: The :tangle property in my test case was set
buffer wide through
--8<---------------cut here---------------start------------->8---
#+PROPERTY: header-args:R :tangle "myfile.R"
--8<---------------cut here---------------end--------------->8---
But still, it produced a warning for each code block. It would
be nicer if that warning was issued only once, IMO. But that is
very minor.
Regards,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 20:02 ` Andreas Leha
@ 2015-05-19 21:03 ` Nicolas Goaziou
2015-05-19 21:10 ` Andreas Leha
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-19 21:03 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode
Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
> But I still get
>
> 191 low Unknown value "none" for header ":results"
Could you show an ECM? I cannot reproduce it.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 21:03 ` Nicolas Goaziou
@ 2015-05-19 21:10 ` Andreas Leha
2015-05-19 21:26 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Andreas Leha @ 2015-05-19 21:10 UTC (permalink / raw)
To: emacs-orgmode
Hi Nicolas,
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
>
>> But I still get
>>
>> 191 low Unknown value "none" for header ":results"
>
> Could you show an ECM? I cannot reproduce it.
>
Sure:
--8<---------------cut here---------------start------------->8---
* Test code block names
#+name: test
#+begin_src R :results none
1:10
#+end_src
--8<---------------cut here---------------end--------------->8---
Tested with "emacs -Q" with the same result:
--8<---------------cut here---------------start------------->8---
4 low Unknown value "none" for header ":results"
--8<---------------cut here---------------end--------------->8---
Regards,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 21:10 ` Andreas Leha
@ 2015-05-19 21:26 ` Nicolas Goaziou
2015-05-19 21:35 ` Andreas Leha
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-19 21:26 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode
Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
> * Test code block names
>
> #+name: test
> #+begin_src R :results none
> 1:10
> #+end_src
OK. It was a R-specific bug. It should now be fixed.
Thank you.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 21:26 ` Nicolas Goaziou
@ 2015-05-19 21:35 ` Andreas Leha
0 siblings, 0 replies; 53+ messages in thread
From: Andreas Leha @ 2015-05-19 21:35 UTC (permalink / raw)
To: emacs-orgmode
Hi Nicolas,
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
>
>> * Test code block names
>>
>> #+name: test
>> #+begin_src R :results none
>> 1:10
>> #+end_src
>
> OK. It was a R-specific bug. It should now be fixed.
>
Thank you! Fix confirmed. The last warning is gone.
Thanks,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-19 13:43 ` Andreas Leha
@ 2015-05-20 15:01 ` Rainer M Krug
2015-05-20 15:08 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-05-20 15:01 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 4277 bytes --]
Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
> Hi Rainer,
>
> Rainer M Krug <Rainer@krugs.de> writes:
>> Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>>
>>> Hello,
>>>
>>> The following library implements linting for Org syntax. The sole public
>>> function is `org-lint', which see.
>>>
>>> Internally, the library defines a new structure: `org-lint-checker',
>>> with the following slots:
>>>
>>> - NAME: Unique check identifier, as a symbol. The check is done
>>> calling the function `org-lint-NAME' with one mandatory argument,
>>> the parse tree describing the current Org buffer. Such function
>>> calls are wrapped within a `save-excursion' and point is always at
>>> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
>>> when POSITION refer to the buffer position of the error, as an
>>> integer, and MESSAGE is a strings describing the error.
>>>
>>> - DESCRIPTION: Summary about the check, as a string.
>>>
>>> - CATEGORIES: Categories relative to the check, as a list of symbol.
>>> They are used for filtering when calling `org-lint'. Checkers not
>>> explicitly associated to a category are collected in the `default'
>>> one.
>>>
>>> - TRUST: The trust level one can have in the check. It is either `low'
>>> or `high', depending on the heuristics implemented and the nature of
>>> the check. This has an indicative value only and is displayed along
>>> reports.
>>>
>>> All checks have to be listed in `org-lint--checkers'.
>>>
>>> Results are displayed in a special "*Org Lint*" buffer with a dedicated
>>> major mode, derived from `tabulated-list-mode'. In addition to the usual
>>> key-bindings inherited from it, "C-j" displays problematic line reported
>>> under point and "RET" jumps to it.
>>>
>>> Checks currently implemented are:
>>>
>>> - duplicates CUSTOM_ID properties
>>> - duplicate NAME values
>>> - duplicate targets
>>> - duplicate footnote definitions
>>> - orphaned affiliated keywords
>>> - obsolete affiliated keywords
>>> - missing language in src blocks
>>> - NAME values with a colon
>>> - wrong header arguments in src blocks
>>> - misuse of CATEGORY keyword
>>> - "coderef" links with unknown destination
>>> - "custom-id" links with unknown destination
>>> - "fuzzy" links with unknown destination
>>> - "id" links with unknown destination
>>> - links to non-existent local files
>>> - special properties in properties drawer
>>> - obsolete syntax for PROPERTIES drawers
>>> - missing definition for footnote references
>>> - missing reference for footnote definitions
>>> - non-footnote definitions in footnote section
>>> - probable invalid keywords
>>> - invalid blocks
>>> - probable incomplete drawers
>>> - obsolete QUOTE section
>>>
>>> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
>>> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
>>> useful enough.
>>>
>>
>> This sounds very interesting and I would like to try it out. I
>> understand that it can't be put into master, but could it be put into a
>> branch?
>>
>> This would make testing a bit easier.
>>
>
> It is. The branch is called `wip-lint'.
Thanks (also to Nicolas) - I found it. Just expected the branch to be
tracked automatically.
This is really brilliant!
But I now get a message in one .org file:
,----
| Org linting process starting...
| Search failed: "^[ ]*#\\+NAME: +tab:sensVar"
`----
and no results.
Works in other .org files.
This one is rather long (11570 lines) and many code blocks.
Just let me know how I can trace down where this is coming from and what
the message tells me.
Thanks,
Rainer
>
> Regards,
> Andreas
>
>
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-20 15:01 ` Rainer M Krug
@ 2015-05-20 15:08 ` Rainer M Krug
2015-05-20 15:24 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-05-20 15:08 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 4598 bytes --]
Rainer M Krug <Rainer@krugs.de> writes:
> Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
>
>> Hi Rainer,
>>
>> Rainer M Krug <Rainer@krugs.de> writes:
>>> Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>>>
>>>> Hello,
>>>>
>>>> The following library implements linting for Org syntax. The sole public
>>>> function is `org-lint', which see.
>>>>
>>>> Internally, the library defines a new structure: `org-lint-checker',
>>>> with the following slots:
>>>>
>>>> - NAME: Unique check identifier, as a symbol. The check is done
>>>> calling the function `org-lint-NAME' with one mandatory argument,
>>>> the parse tree describing the current Org buffer. Such function
>>>> calls are wrapped within a `save-excursion' and point is always at
>>>> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
>>>> when POSITION refer to the buffer position of the error, as an
>>>> integer, and MESSAGE is a strings describing the error.
>>>>
>>>> - DESCRIPTION: Summary about the check, as a string.
>>>>
>>>> - CATEGORIES: Categories relative to the check, as a list of symbol.
>>>> They are used for filtering when calling `org-lint'. Checkers not
>>>> explicitly associated to a category are collected in the `default'
>>>> one.
>>>>
>>>> - TRUST: The trust level one can have in the check. It is either `low'
>>>> or `high', depending on the heuristics implemented and the nature of
>>>> the check. This has an indicative value only and is displayed along
>>>> reports.
>>>>
>>>> All checks have to be listed in `org-lint--checkers'.
>>>>
>>>> Results are displayed in a special "*Org Lint*" buffer with a dedicated
>>>> major mode, derived from `tabulated-list-mode'. In addition to the usual
>>>> key-bindings inherited from it, "C-j" displays problematic line reported
>>>> under point and "RET" jumps to it.
>>>>
>>>> Checks currently implemented are:
>>>>
>>>> - duplicates CUSTOM_ID properties
>>>> - duplicate NAME values
>>>> - duplicate targets
>>>> - duplicate footnote definitions
>>>> - orphaned affiliated keywords
>>>> - obsolete affiliated keywords
>>>> - missing language in src blocks
>>>> - NAME values with a colon
>>>> - wrong header arguments in src blocks
>>>> - misuse of CATEGORY keyword
>>>> - "coderef" links with unknown destination
>>>> - "custom-id" links with unknown destination
>>>> - "fuzzy" links with unknown destination
>>>> - "id" links with unknown destination
>>>> - links to non-existent local files
>>>> - special properties in properties drawer
>>>> - obsolete syntax for PROPERTIES drawers
>>>> - missing definition for footnote references
>>>> - missing reference for footnote definitions
>>>> - non-footnote definitions in footnote section
>>>> - probable invalid keywords
>>>> - invalid blocks
>>>> - probable incomplete drawers
>>>> - obsolete QUOTE section
>>>>
>>>> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
>>>> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
>>>> useful enough.
>>>>
>>>
>>> This sounds very interesting and I would like to try it out. I
>>> understand that it can't be put into master, but could it be put into a
>>> branch?
>>>
>>> This would make testing a bit easier.
>>>
>>
>> It is. The branch is called `wip-lint'.
>
> Thanks (also to Nicolas) - I found it. Just expected the branch to be
> tracked automatically.
>
> This is really brilliant!
>
> But I now get a message in one .org file:
>
> ,----
> | Org linting process starting...
> | Search failed: "^[ ]*#\\+NAME: +tab:sensVar"
> `----
>
> and no results.
>
> Works in other .org files.
>
> This one is rather long (11570 lines) and many code blocks.
>
> Just let me know how I can trace down where this is coming from and what
> the message tells me.
It seems that the error comes from the fact that ~#+LABEL: sensVar~ was
defined twice.
Renaming these results in working linting.
Rainer
>
> Thanks,
>
> Rainer
>
>>
>> Regards,
>> Andreas
>>
>>
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-20 15:08 ` Rainer M Krug
@ 2015-05-20 15:24 ` Rainer M Krug
2015-05-20 20:42 ` Andreas Leha
2015-05-20 21:46 ` Nicolas Goaziou
0 siblings, 2 replies; 53+ messages in thread
From: Rainer M Krug @ 2015-05-20 15:24 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 5644 bytes --]
Rainer M Krug <Rainer@krugs.de> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
>>
>>> Hi Rainer,
>>>
>>> Rainer M Krug <Rainer@krugs.de> writes:
>>>> Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>>>>
>>>>> Hello,
>>>>>
>>>>> The following library implements linting for Org syntax. The sole public
>>>>> function is `org-lint', which see.
>>>>>
>>>>> Internally, the library defines a new structure: `org-lint-checker',
>>>>> with the following slots:
>>>>>
>>>>> - NAME: Unique check identifier, as a symbol. The check is done
>>>>> calling the function `org-lint-NAME' with one mandatory argument,
>>>>> the parse tree describing the current Org buffer. Such function
>>>>> calls are wrapped within a `save-excursion' and point is always at
>>>>> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
>>>>> when POSITION refer to the buffer position of the error, as an
>>>>> integer, and MESSAGE is a strings describing the error.
>>>>>
>>>>> - DESCRIPTION: Summary about the check, as a string.
>>>>>
>>>>> - CATEGORIES: Categories relative to the check, as a list of symbol.
>>>>> They are used for filtering when calling `org-lint'. Checkers not
>>>>> explicitly associated to a category are collected in the `default'
>>>>> one.
>>>>>
>>>>> - TRUST: The trust level one can have in the check. It is either `low'
>>>>> or `high', depending on the heuristics implemented and the nature of
>>>>> the check. This has an indicative value only and is displayed along
>>>>> reports.
>>>>>
>>>>> All checks have to be listed in `org-lint--checkers'.
>>>>>
>>>>> Results are displayed in a special "*Org Lint*" buffer with a dedicated
>>>>> major mode, derived from `tabulated-list-mode'. In addition to the usual
>>>>> key-bindings inherited from it, "C-j" displays problematic line reported
>>>>> under point and "RET" jumps to it.
>>>>>
>>>>> Checks currently implemented are:
>>>>>
>>>>> - duplicates CUSTOM_ID properties
>>>>> - duplicate NAME values
>>>>> - duplicate targets
>>>>> - duplicate footnote definitions
>>>>> - orphaned affiliated keywords
>>>>> - obsolete affiliated keywords
>>>>> - missing language in src blocks
>>>>> - NAME values with a colon
>>>>> - wrong header arguments in src blocks
>>>>> - misuse of CATEGORY keyword
>>>>> - "coderef" links with unknown destination
>>>>> - "custom-id" links with unknown destination
>>>>> - "fuzzy" links with unknown destination
>>>>> - "id" links with unknown destination
>>>>> - links to non-existent local files
>>>>> - special properties in properties drawer
>>>>> - obsolete syntax for PROPERTIES drawers
>>>>> - missing definition for footnote references
>>>>> - missing reference for footnote definitions
>>>>> - non-footnote definitions in footnote section
>>>>> - probable invalid keywords
>>>>> - invalid blocks
>>>>> - probable incomplete drawers
>>>>> - obsolete QUOTE section
>>>>>
>>>>> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
>>>>> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
>>>>> useful enough.
>>>>>
>>>>
>>>> This sounds very interesting and I would like to try it out. I
>>>> understand that it can't be put into master, but could it be put into a
>>>> branch?
>>>>
>>>> This would make testing a bit easier.
>>>>
>>>
>>> It is. The branch is called `wip-lint'.
>>
>> Thanks (also to Nicolas) - I found it. Just expected the branch to be
>> tracked automatically.
>>
>> This is really brilliant!
>>
>> But I now get a message in one .org file:
>>
>> ,----
>> | Org linting process starting...
>> | Search failed: "^[ ]*#\\+NAME: +tab:sensVar"
>> `----
>>
>> and no results.
>>
>> Works in other .org files.
>>
>> This one is rather long (11570 lines) and many code blocks.
>>
>> Just let me know how I can trace down where this is coming from and what
>> the message tells me.
>
> It seems that the error comes from the fact that ~#+LABEL: sensVar~ was
> defined twice.
>
> Renaming these results in working linting.
OK - please ignore this last comment.
There is an example where I get the error:
--8<---------------cut here---------------start------------->8---
* Fitting the kernel to the data
The parameter which will be fitted can be found in Table [[tab:fitInitial]]
#+CAPTION: Variables used for the initial fit of the wind profile using the function and the initial values.
#+LABEL: tab:fitInitial
| variable | initial value | remark |
|--------------------+---------------+--------------------------------------------------|
--8<---------------cut here---------------end--------------->8---
The cause is the link [[tab:initial]] If I remove everything below and
including the line #+CAPTION the linting works.
,----
| 2 high Unknown fuzzy location "tab:fitInitial"
`----
Cheers,
Rainer
>
> Rainer
>
>>
>> Thanks,
>>
>> Rainer
>>
>>>
>>> Regards,
>>> Andreas
>>>
>>>
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-20 15:24 ` Rainer M Krug
@ 2015-05-20 20:42 ` Andreas Leha
2015-05-20 21:15 ` Rainer M Krug
2015-05-20 21:46 ` Nicolas Goaziou
1 sibling, 1 reply; 53+ messages in thread
From: Andreas Leha @ 2015-05-20 20:42 UTC (permalink / raw)
To: emacs-orgmode
Hi Rainer,
Rainer M Krug <Rainer@krugs.de> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> Rainer M Krug <Rainer@krugs.de> writes:
>>
>>> Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
>>>
>>>> Hi Rainer,
>>>>
>>>> Rainer M Krug <Rainer@krugs.de> writes:
>>>>> Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>>>>>
>>>>>> Hello,
>>>>>>
>>>>>> The following library implements linting for Org syntax. The sole public
>>>>>> function is `org-lint', which see.
>>>>>>
>>>>>> Internally, the library defines a new structure: `org-lint-checker',
>>>>>> with the following slots:
>>>>>>
>>>>>> - NAME: Unique check identifier, as a symbol. The check is done
>>>>>> calling the function `org-lint-NAME' with one mandatory argument,
>>>>>> the parse tree describing the current Org buffer. Such function
>>>>>> calls are wrapped within a `save-excursion' and point is always at
>>>>>> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
>>>>>> when POSITION refer to the buffer position of the error, as an
>>>>>> integer, and MESSAGE is a strings describing the error.
>>>>>>
>>>>>> - DESCRIPTION: Summary about the check, as a string.
>>>>>>
>>>>>> - CATEGORIES: Categories relative to the check, as a list of symbol.
>>>>>> They are used for filtering when calling `org-lint'. Checkers not
>>>>>> explicitly associated to a category are collected in the `default'
>>>>>> one.
>>>>>>
>>>>>> - TRUST: The trust level one can have in the check. It is either `low'
>>>>>> or `high', depending on the heuristics implemented and the nature of
>>>>>> the check. This has an indicative value only and is displayed along
>>>>>> reports.
>>>>>>
>>>>>> All checks have to be listed in `org-lint--checkers'.
>>>>>>
>>>>>> Results are displayed in a special "*Org Lint*" buffer with a dedicated
>>>>>> major mode, derived from `tabulated-list-mode'. In addition to the usual
>>>>>> key-bindings inherited from it, "C-j" displays problematic line reported
>>>>>> under point and "RET" jumps to it.
>>>>>>
>>>>>> Checks currently implemented are:
>>>>>>
>>>>>> - duplicates CUSTOM_ID properties
>>>>>> - duplicate NAME values
>>>>>> - duplicate targets
>>>>>> - duplicate footnote definitions
>>>>>> - orphaned affiliated keywords
>>>>>> - obsolete affiliated keywords
>>>>>> - missing language in src blocks
>>>>>> - NAME values with a colon
>>>>>> - wrong header arguments in src blocks
>>>>>> - misuse of CATEGORY keyword
>>>>>> - "coderef" links with unknown destination
>>>>>> - "custom-id" links with unknown destination
>>>>>> - "fuzzy" links with unknown destination
>>>>>> - "id" links with unknown destination
>>>>>> - links to non-existent local files
>>>>>> - special properties in properties drawer
>>>>>> - obsolete syntax for PROPERTIES drawers
>>>>>> - missing definition for footnote references
>>>>>> - missing reference for footnote definitions
>>>>>> - non-footnote definitions in footnote section
>>>>>> - probable invalid keywords
>>>>>> - invalid blocks
>>>>>> - probable incomplete drawers
>>>>>> - obsolete QUOTE section
>>>>>>
>>>>>> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
>>>>>> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
>>>>>> useful enough.
>>>>>>
>>>>>
>>>>> This sounds very interesting and I would like to try it out. I
>>>>> understand that it can't be put into master, but could it be put into a
>>>>> branch?
>>>>>
>>>>> This would make testing a bit easier.
>>>>>
>>>>
>>>> It is. The branch is called `wip-lint'.
>>>
>>> Thanks (also to Nicolas) - I found it. Just expected the branch to be
>>> tracked automatically.
>>>
>>> This is really brilliant!
>>>
>>> But I now get a message in one .org file:
>>>
>>> ,----
>>> | Org linting process starting...
>>> | Search failed: "^[ ]*#\\+NAME: +tab:sensVar"
>>> `----
>>>
>>> and no results.
>>>
>>> Works in other .org files.
>>>
>>> This one is rather long (11570 lines) and many code blocks.
>>>
>>> Just let me know how I can trace down where this is coming from and what
>>> the message tells me.
>>
>> It seems that the error comes from the fact that ~#+LABEL: sensVar~ was
>> defined twice.
>>
>> Renaming these results in working linting.
>
> OK - please ignore this last comment.
>
> There is an example where I get the error:
>
> * Fitting the kernel to the data
> The parameter which will be fitted can be found in Table [[tab:fitInitial]]
>
> #+CAPTION: Variables used for the initial fit of the wind profile using the function and the initial values.
> #+LABEL: tab:fitInitial
> | variable | initial value | remark |
> |--------------------+---------------+--------------------------------------------------|
>
> The cause is the link [[tab:initial]] If I remove everything below and
> including the line #+CAPTION the linting works.
>
> ,----
> | 2 high Unknown fuzzy location "tab:fitInitial"
> `----
>
Untested - but should that not be
#+NAME: tab:fitInitial
rather than #+LABEL?
Cheers,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-20 20:42 ` Andreas Leha
@ 2015-05-20 21:15 ` Rainer M Krug
0 siblings, 0 replies; 53+ messages in thread
From: Rainer M Krug @ 2015-05-20 21:15 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode@gnu.org
Envoyé de mon iPhone
> Le 20 mai 2015 à 22:42, Andreas Leha <andreas.leha@med.uni-goettingen.de> a écrit :
>
> Hi Rainer,
>
> Rainer M Krug <Rainer@krugs.de> writes:
>> Rainer M Krug <Rainer@krugs.de> writes:
>>
>>> Rainer M Krug <Rainer@krugs.de> writes:
>>>
>>>> Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
>>>>
>>>>> Hi Rainer,
>>>>>
>>>>> Rainer M Krug <Rainer@krugs.de> writes:
>>>>>> Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>> The following library implements linting for Org syntax. The sole public
>>>>>>> function is `org-lint', which see.
>>>>>>>
>>>>>>> Internally, the library defines a new structure: `org-lint-checker',
>>>>>>> with the following slots:
>>>>>>>
>>>>>>> - NAME: Unique check identifier, as a symbol. The check is done
>>>>>>> calling the function `org-lint-NAME' with one mandatory argument,
>>>>>>> the parse tree describing the current Org buffer. Such function
>>>>>>> calls are wrapped within a `save-excursion' and point is always at
>>>>>>> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
>>>>>>> when POSITION refer to the buffer position of the error, as an
>>>>>>> integer, and MESSAGE is a strings describing the error.
>>>>>>>
>>>>>>> - DESCRIPTION: Summary about the check, as a string.
>>>>>>>
>>>>>>> - CATEGORIES: Categories relative to the check, as a list of symbol.
>>>>>>> They are used for filtering when calling `org-lint'. Checkers not
>>>>>>> explicitly associated to a category are collected in the `default'
>>>>>>> one.
>>>>>>>
>>>>>>> - TRUST: The trust level one can have in the check. It is either `low'
>>>>>>> or `high', depending on the heuristics implemented and the nature of
>>>>>>> the check. This has an indicative value only and is displayed along
>>>>>>> reports.
>>>>>>>
>>>>>>> All checks have to be listed in `org-lint--checkers'.
>>>>>>>
>>>>>>> Results are displayed in a special "*Org Lint*" buffer with a dedicated
>>>>>>> major mode, derived from `tabulated-list-mode'. In addition to the usual
>>>>>>> key-bindings inherited from it, "C-j" displays problematic line reported
>>>>>>> under point and "RET" jumps to it.
>>>>>>>
>>>>>>> Checks currently implemented are:
>>>>>>>
>>>>>>> - duplicates CUSTOM_ID properties
>>>>>>> - duplicate NAME values
>>>>>>> - duplicate targets
>>>>>>> - duplicate footnote definitions
>>>>>>> - orphaned affiliated keywords
>>>>>>> - obsolete affiliated keywords
>>>>>>> - missing language in src blocks
>>>>>>> - NAME values with a colon
>>>>>>> - wrong header arguments in src blocks
>>>>>>> - misuse of CATEGORY keyword
>>>>>>> - "coderef" links with unknown destination
>>>>>>> - "custom-id" links with unknown destination
>>>>>>> - "fuzzy" links with unknown destination
>>>>>>> - "id" links with unknown destination
>>>>>>> - links to non-existent local files
>>>>>>> - special properties in properties drawer
>>>>>>> - obsolete syntax for PROPERTIES drawers
>>>>>>> - missing definition for footnote references
>>>>>>> - missing reference for footnote definitions
>>>>>>> - non-footnote definitions in footnote section
>>>>>>> - probable invalid keywords
>>>>>>> - invalid blocks
>>>>>>> - probable incomplete drawers
>>>>>>> - obsolete QUOTE section
>>>>>>>
>>>>>>> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
>>>>>>> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
>>>>>>> useful enough.
>>>>>>
>>>>>> This sounds very interesting and I would like to try it out. I
>>>>>> understand that it can't be put into master, but could it be put into a
>>>>>> branch?
>>>>>>
>>>>>> This would make testing a bit easier.
>>>>>
>>>>> It is. The branch is called `wip-lint'.
>>>>
>>>> Thanks (also to Nicolas) - I found it. Just expected the branch to be
>>>> tracked automatically.
>>>>
>>>> This is really brilliant!
>>>>
>>>> But I now get a message in one .org file:
>>>>
>>>> ,----
>>>> | Org linting process starting...
>>>> | Search failed: "^[ ]*#\\+NAME: +tab:sensVar"
>>>> `----
>>>>
>>>> and no results.
>>>>
>>>> Works in other .org files.
>>>>
>>>> This one is rather long (11570 lines) and many code blocks.
>>>>
>>>> Just let me know how I can trace down where this is coming from and what
>>>> the message tells me.
>>>
>>> It seems that the error comes from the fact that ~#+LABEL: sensVar~ was
>>> defined twice.
>>>
>>> Renaming these results in working linting.
>>
>> OK - please ignore this last comment.
>>
>> There is an example where I get the error:
>>
>> * Fitting the kernel to the data
>> The parameter which will be fitted can be found in Table [[tab:fitInitial]]
>>
>> #+CAPTION: Variables used for the initial fit of the wind profile using the function and the initial values.
>> #+LABEL: tab:fitInitial
>> | variable | initial value | remark |
>> |--------------------+---------------+--------------------------------------------------|
>>
>> The cause is the link [[tab:initial]] If I remove everything below and
>> including the line #+CAPTION the linting works.
>>
>> ,----
>> | 2 high Unknown fuzzy location "tab:fitInitial"
>> `----
>
> Untested - but should that not be
> #+NAME: tab:fitInitial
> rather than #+LABEL?
>
Yes - that would be correct. But the linting should tell me that instead of failing with this message
Cheers,
Rainer
> Cheers,
> Andreas
>
>
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-20 15:24 ` Rainer M Krug
2015-05-20 20:42 ` Andreas Leha
@ 2015-05-20 21:46 ` Nicolas Goaziou
2015-05-21 8:40 ` Rainer M Krug
1 sibling, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-20 21:46 UTC (permalink / raw)
To: Rainer M Krug; +Cc: emacs-orgmode
Rainer M Krug <Rainer@krugs.de> writes:
> There is an example where I get the error:
>
> * Fitting the kernel to the data
> The parameter which will be fitted can be found in Table [[tab:fitInitial]]
>
> #+CAPTION: Variables used for the initial fit of the wind profile using the function and the initial values.
> #+LABEL: tab:fitInitial
> | variable | initial value | remark |
> |--------------------+---------------+--------------------------------------------------|
>
> The cause is the link [[tab:initial]] If I remove everything below and
> including the line #+CAPTION the linting works.
Fixed. Thank you.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-20 21:46 ` Nicolas Goaziou
@ 2015-05-21 8:40 ` Rainer M Krug
2015-05-21 16:24 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-05-21 8:40 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 2269 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> There is an example where I get the error:
>>
>> * Fitting the kernel to the data
>> The parameter which will be fitted can be found in Table [[tab:fitInitial]]
>>
>> #+CAPTION: Variables used for the initial fit of the wind profile using the function and the initial values.
>> #+LABEL: tab:fitInitial
>> | variable | initial value | remark |
>> |--------------------+---------------+--------------------------------------------------|
>>
>> The cause is the link [[tab:initial]] If I remove everything below and
>> including the line #+CAPTION the linting works.
>
> Fixed. Thank you.
>
Thanks.
Two more questions:
I get the following warnings:
,----
| 10 low Unknown OPTIONS item "@"
| 11 low Unknown OPTIONS item "skip"
| 11 low Unknown OPTIONS item "LaTeX"
| 11 low Unknown OPTIONS item "TeX"
`----
based on the following lines:
,----
| #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
| #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
`----
The file is not that old - but have these options changed?
and I get
,----
| 1821 low Orphaned affiliated keyword: "RESULTS"
`----
caused by an orphaned
,----
| #+RESULTS:
`----
But these are created by evaluating a code block which produced no
results - so they are a valid part of the document?
And an error:
I get, in the same document I got the other errors, the following error:
,----
| Org linting process starting...
| org-split-string: Wrong type argument: stringp, 292
`----
The backtrace is huge - how can I produce a usable backtrace?
Hope this helps,
Rainer
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-21 8:40 ` Rainer M Krug
@ 2015-05-21 16:24 ` Nicolas Goaziou
2015-05-21 18:18 ` Rainer M Krug
` (2 more replies)
0 siblings, 3 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-21 16:24 UTC (permalink / raw)
To: Rainer M Krug; +Cc: emacs-orgmode
Rainer M Krug <Rainer@krugs.de> writes:
> Two more questions:
>
> I get the following warnings:
>
> ,----
> | 10 low Unknown OPTIONS item "@"
> | 11 low Unknown OPTIONS item "skip"
> | 11 low Unknown OPTIONS item "LaTeX"
> | 11 low Unknown OPTIONS item "TeX"
> `----
>
> based on the following lines:
>
> ,----
> | #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
> | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
> `----
>
> The file is not that old - but have these options changed?
These options do not do anything. "@" and "skip" have no equivalent.
"TeX" and "LaTeX" are now "tex". See (info "(org) Export settings").
> and I get
>
> ,----
> | 1821 low Orphaned affiliated keyword: "RESULTS"
> `----
>
> caused by an orphaned
>
> ,----
> | #+RESULTS:
> `----
>
> But these are created by evaluating a code block which produced no
> results - so they are a valid part of the document?
Correct. Note however the "low" trust on this check. It's just
a heads-up. Anyway I remove such reports for RESULTS in wip-lint.
> And an error:
>
> I get, in the same document I got the other errors, the following error:
>
> ,----
> | Org linting process starting...
> | org-split-string: Wrong type argument: stringp, 292
> `----
>
> The backtrace is huge - how can I produce a usable backtrace?
Usually, only the last top-level function call is useful.
It would be better to provide an ECM, tho. The error comes from Babel
header check. Does "292" ring a bell in a #+HEADER: line?
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-21 16:24 ` Nicolas Goaziou
@ 2015-05-21 18:18 ` Rainer M Krug
2015-05-21 18:23 ` Rainer M Krug
2015-05-21 18:30 ` Rainer M Krug
2 siblings, 0 replies; 53+ messages in thread
From: Rainer M Krug @ 2015-05-21 18:18 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 2420 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> Two more questions:
>>
>> I get the following warnings:
>>
>> ,----
>> | 10 low Unknown OPTIONS item "@"
>> | 11 low Unknown OPTIONS item "skip"
>> | 11 low Unknown OPTIONS item "LaTeX"
>> | 11 low Unknown OPTIONS item "TeX"
>> `----
>>
>> based on the following lines:
>>
>> ,----
>> | #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
>> | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
>> `----
>>
>> The file is not that old - but have these options changed?
>
> These options do not do anything. "@" and "skip" have no equivalent.
> "TeX" and "LaTeX" are now "tex". See (info "(org) Export settings").
>
>> and I get
>>
>> ,----
>> | 1821 low Orphaned affiliated keyword: "RESULTS"
>> `----
>>
>> caused by an orphaned
>>
>> ,----
>> | #+RESULTS:
>> `----
>>
>> But these are created by evaluating a code block which produced no
>> results - so they are a valid part of the document?
>
> Correct. Note however the "low" trust on this check. It's just
> a heads-up. Anyway I remove such reports for RESULTS in wip-lint.
>
>> And an error:
>>
>> I get, in the same document I got the other errors, the following error:
>>
>> ,----
>> | Org linting process starting...
>> | org-split-string: Wrong type argument: stringp, 292
>> `----
>>
>> The backtrace is huge - how can I produce a usable backtrace?
>
> Usually, only the last top-level function call is useful.
>
> It would be better to provide an ECM, tho. The error comes from Babel
> header check. Does "292" ring a bell in a #+HEADER: line?
Hi
here is an ECM:
,----
| * Matlab code
|
| #+begin_src octave
|
| #+end_src
`----
Actually, whatever I put there instead of octave, I get the same error.
This is very strange. What is the problem here?
Cheers,
Rainer
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-21 16:24 ` Nicolas Goaziou
2015-05-21 18:18 ` Rainer M Krug
@ 2015-05-21 18:23 ` Rainer M Krug
2015-05-21 18:30 ` Rainer M Krug
2 siblings, 0 replies; 53+ messages in thread
From: Rainer M Krug @ 2015-05-21 18:23 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 2358 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> Two more questions:
>>
>> I get the following warnings:
>>
>> ,----
>> | 10 low Unknown OPTIONS item "@"
>> | 11 low Unknown OPTIONS item "skip"
>> | 11 low Unknown OPTIONS item "LaTeX"
>> | 11 low Unknown OPTIONS item "TeX"
>> `----
>>
>> based on the following lines:
>>
>> ,----
>> | #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
>> | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
>> `----
>>
>> The file is not that old - but have these options changed?
>
> These options do not do anything. "@" and "skip" have no equivalent.
> "TeX" and "LaTeX" are now "tex". See (info "(org) Export settings").
>
>> and I get
>>
>> ,----
>> | 1821 low Orphaned affiliated keyword: "RESULTS"
>> `----
>>
>> caused by an orphaned
>>
>> ,----
>> | #+RESULTS:
>> `----
>>
>> But these are created by evaluating a code block which produced no
>> results - so they are a valid part of the document?
>
> Correct. Note however the "low" trust on this check. It's just
> a heads-up. Anyway I remove such reports for RESULTS in wip-lint.
>
>> And an error:
>>
>> I get, in the same document I got the other errors, the following error:
>>
>> ,----
>> | Org linting process starting...
>> | org-split-string: Wrong type argument: stringp, 292
>> `----
>>
>> The backtrace is huge - how can I produce a usable backtrace?
>
> Usually, only the last top-level function call is useful.
>
> It would be better to provide an ECM, tho. The error comes from Babel
> header check. Does "292" ring a bell in a #+HEADER: line?
Addition to my last email: when I close emacs and open it again and try
to linter the ECM, it works - is it possible that there is some caching
which is not cleaned up?
Rainer
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-21 16:24 ` Nicolas Goaziou
2015-05-21 18:18 ` Rainer M Krug
2015-05-21 18:23 ` Rainer M Krug
@ 2015-05-21 18:30 ` Rainer M Krug
2015-05-21 21:53 ` Nicolas Goaziou
2 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-05-21 18:30 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 2574 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> Two more questions:
>>
>> I get the following warnings:
>>
>> ,----
>> | 10 low Unknown OPTIONS item "@"
>> | 11 low Unknown OPTIONS item "skip"
>> | 11 low Unknown OPTIONS item "LaTeX"
>> | 11 low Unknown OPTIONS item "TeX"
>> `----
>>
>> based on the following lines:
>>
>> ,----
>> | #+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:nil -:t f:t *:t <:t
>> | #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
>> `----
>>
>> The file is not that old - but have these options changed?
>
> These options do not do anything. "@" and "skip" have no equivalent.
> "TeX" and "LaTeX" are now "tex". See (info "(org) Export settings").
>
>> and I get
>>
>> ,----
>> | 1821 low Orphaned affiliated keyword: "RESULTS"
>> `----
>>
>> caused by an orphaned
>>
>> ,----
>> | #+RESULTS:
>> `----
>>
>> But these are created by evaluating a code block which produced no
>> results - so they are a valid part of the document?
>
> Correct. Note however the "low" trust on this check. It's just
> a heads-up. Anyway I remove such reports for RESULTS in wip-lint.
>
>> And an error:
>>
>> I get, in the same document I got the other errors, the following error:
>>
>> ,----
>> | Org linting process starting...
>> | org-split-string: Wrong type argument: stringp, 292
>> `----
>>
>> The backtrace is huge - how can I produce a usable backtrace?
>
> Usually, only the last top-level function call is useful.
>
> It would be better to provide an ECM, tho. The error comes from Babel
> header check. Does "292" ring a bell in a #+HEADER: line?
Well - now it does. The following produces the error:
--8<---------------cut here---------------start------------->8---
#+PROPERTY: header-args :tangle-mode (identity #o444)
* Some code
#+begin_src R :results nons
#+end_src
--8<---------------cut here---------------end--------------->8---
The problem is the (identity #o444) which is causing the problem.
Here it is,
Rainer
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-21 18:30 ` Rainer M Krug
@ 2015-05-21 21:53 ` Nicolas Goaziou
2015-05-22 8:10 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-21 21:53 UTC (permalink / raw)
To: Rainer M Krug; +Cc: emacs-orgmode
Rainer M Krug <Rainer@krugs.de> writes:
> Well - now it does. The following produces the error:
>
> #+PROPERTY: header-args :tangle-mode (identity #o444)
>
> * Some code
>
> #+begin_src R :results nons
>
> #+end_src
>
> The problem is the (identity #o444) which is causing the problem.
Fixed. Thank you.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-21 21:53 ` Nicolas Goaziou
@ 2015-05-22 8:10 ` Rainer M Krug
2015-05-22 19:08 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-05-22 8:10 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 5355 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> Well - now it does. The following produces the error:
>>
>> #+PROPERTY: header-args :tangle-mode (identity #o444)
>>
>> * Some code
>>
>> #+begin_src R :results nons
>>
>> #+end_src
>>
>> The problem is the (identity #o444) which is causing the problem.
>
> Fixed. Thank you.
Thanks - working.
Now there re a few more lints giving wrong warnings:
1) not identifying header argument with +
,----
| #+PROPERTY: header-args+ :tangle no
`----
results in
,----
| 87 high Unknown header argument ""
`----
2) not knowing header argument "file-ext" from R
,----
| #+begin_src R :exports results :file-ext pdf :results graphics :width 8 :height 8
| plotSensMainEffAll(files)
| #+end_src
`----
results in
,----
| 1691 high Unknown header argument "file-ext"
`----
3) I am not to sure about this one, but in LaTeX labels of figures are
with the colon. Initially, I had #+LABEL: instead of #+NAME: but changed
it as one should use #+NAME instead of #+LABEL, but now I get the following:
,----
| #+CAPTION: The caption
| #+NAME: fig:sensDefault
| #+RESULTS: fig_sensDefault
| [[file:./output/fig_sensDefault.pdf]]
`----
results in
,----
| 1686 high Name "fig:sensDefault" contains a colon; Babel cannot use it as input
`----
I agree with the fact that Babel can not use it as input, but I do not
want to use it as input, only as a label in LaTeX for the figure?
According to the manual this should work:
http://orgmode.org/manual/Images-and-tables.html:
,----
| #+CAPTION: This is the caption for the next figure link (or table)
| #+NAME: fig:SED-HR4049
| [[./img/a.jpg]]
`----
So maybe check if this is part of a construct with a CAPTION or if it
really is used as an input somewhere?
4) references where :FILE is a normal PROPERTY: (or isn't it?)
,----
| ** Koivusalo2002 - Snow processes in a forest clearing and in a coniferous forest
| :PROPERTIES:
| :TITLE: Snow processes in a forest clearing and in a coniferous forest
| :BTYPE: article
| :CUSTOM_ID: Koivusalo2002
| :AUTHOR: Koivusalo, H. and Kokkonen, T.
| :DOI: 10.1016/S0022-1694(02)00031-8
| :FILE: file:./Literature/Koivusalo_2002.pdf
| :ISSN: 00221694
| :JOURNAL: Journal of Hydrology
| :KEYWORDS: energy,forest,mathematical models,melt,snow,uxes
| :MENDELEY-GROUPS: Energy Balance,bibliography
| :MONTH: may
| :NUMBER: 1-4
| :PAGES: 145--164
| :URL: http://linkinghub.elsevier.com/retrieve/pii/S0022169402000318
| :VOLUME: 262
| :YEAR: 2002
| :END:
| [[file:Literature/Koivusalo2002.pdf]]
`----
results in
,----
| 11221 high Special property "FILE" found in a properties drawer
`----
That is all I can see at the moment.
Here is the ECM:
--8<---------------cut here---------------start------------->8---
#+PROPERTY: header-args :tangle-mode (identity #o444)
#+PROPERTY: header-args :tangle-mode (identity #o444)
#+PROPERTY: header-args+ :tangle no
* file-ext
#+begin_src R :exports results :file-ext pdf :results graphics :width 8 :height 8
cat(23)
#+end_src
* And the : in NAME
#+CAPTION: The caption
#+NAME: fig:sensDefault
#+RESULTS: fig_sensDefault
[[file:./output/fig_sensDefault.pdf]]
* References
** Mahat2013 - Testing above- and below-canopy representations of turbulent fluxes in an energy balance snowmelt model
:PROPERTIES:
:TITLE: Testing above- and below-canopy representations of turbulent fluxes in an energy balance snowmelt model
:BTYPE: article
:CUSTOM_ID: Mahat2013
:AUTHOR: Mahat, Vinod and Tarboton, David G. and Molotch, Noah P.
:DOI: 10.1002/wrcr.20073
:FILE: :Users/rainerkrug/Documents/Mendeley/Files/Mahat, Tarboton, Molotch/Mahat, Tarboton, Molotch\_2013\_Testing above- and below-canopy representations of turbulent fluxes in an energy balance snowmelt model.pdf:pdf
:ISSN: 00431397
:JOURNAL: Water Resources Research
:MONTH: feb
:NUMBER: 2
:PAGES: 1107--1122
:URL: http://doi.wiley.com/10.1002/wrcr.20073
:VOLUME: 49
:YEAR: 2013
:END:
[[file:Literature/Mahat2013.pdf]]
--8<---------------cut here---------------end--------------->8---
which results in
,----
| 3 high Unknown header argument ""
| 8 high Unknown header argument "file-ext"
| 15 high Name "fig:sensDefault" contains a colon; Babel cannot use it as input
| 17 low Link to non-existent local file "./output/fig_sensDefault.pdf"
| 28 high Special property "FILE" found in a properties drawer
| 38 low Link to non-existent local file "Literature/Mahat2013.pdf"
`----
The "Link to non-existent ..." are obvious.
I am really happy with org-lint - thanks a lot. This makes working with
org files much easier.
Thanks,
Rainer
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-22 8:10 ` Rainer M Krug
@ 2015-05-22 19:08 ` Nicolas Goaziou
2015-05-23 12:00 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-22 19:08 UTC (permalink / raw)
To: Rainer M Krug; +Cc: emacs-orgmode
Rainer M Krug <Rainer@krugs.de> writes:
> 1) not identifying header argument with +
> ,----
> | #+PROPERTY: header-args+ :tangle no
> `----
>
> results in
>
> ,----
> | 87 high Unknown header argument ""
> `----
This should be fixed.
> 2) not knowing header argument "file-ext" from R
> ,----
> | #+begin_src R :exports results :file-ext pdf :results graphics :width 8 :height 8
> | plotSensMainEffAll(files)
> | #+end_src
> `----
>
> results in
>
> ,----
> | 1691 high Unknown header argument "file-ext"
> `----
Fixed too.
> 3) I am not to sure about this one, but in LaTeX labels of figures are
> with the colon. Initially, I had #+LABEL: instead of #+NAME: but changed
> it as one should use #+NAME instead of #+LABEL, but now I get the following:
>
> ,----
> | #+CAPTION: The caption
> | #+NAME: fig:sensDefault
> | #+RESULTS: fig_sensDefault
> | [[file:./output/fig_sensDefault.pdf]]
> `----
>
> results in
>
> ,----
> | 1686 high Name "fig:sensDefault" contains a colon; Babel cannot use it as input
> `----
>
> I agree with the fact that Babel can not use it as input, but I do not
> want to use it as input, only as a label in LaTeX for the figure?
Then you can ignore safely this report.
> According to the manual this should work:
>
> http://orgmode.org/manual/Images-and-tables.html:
>
> ,----
> | #+CAPTION: This is the caption for the next figure link (or table)
> | #+NAME: fig:SED-HR4049
> | [[./img/a.jpg]]
> `----
>
> So maybe check if this is part of a construct with a CAPTION or if it
> really is used as an input somewhere?
It is quite complicated to check if it is an input somewhere, e.g., it
could be used as an input in another document.
> 4) references where :FILE is a normal PROPERTY: (or isn't it?)
>
> ,----
> | ** Koivusalo2002 - Snow processes in a forest clearing and in a coniferous forest
> | :PROPERTIES:
> | :TITLE: Snow processes in a forest clearing and in a coniferous forest
> | :BTYPE: article
> | :CUSTOM_ID: Koivusalo2002
> | :AUTHOR: Koivusalo, H. and Kokkonen, T.
> | :DOI: 10.1016/S0022-1694(02)00031-8
> | :FILE: file:./Literature/Koivusalo_2002.pdf
> | :ISSN: 00221694
> | :JOURNAL: Journal of Hydrology
> | :KEYWORDS: energy,forest,mathematical models,melt,snow,uxes
> | :MENDELEY-GROUPS: Energy Balance,bibliography
> | :MONTH: may
> | :NUMBER: 1-4
> | :PAGES: 145--164
> | :URL: http://linkinghub.elsevier.com/retrieve/pii/S0022169402000318
> | :VOLUME: 262
> | :YEAR: 2002
> | :END:
> | [[file:Literature/Koivusalo2002.pdf]]
> `----
>
> results in
>
> ,----
> | 11221 high Special property "FILE" found in a properties drawer
> `----
"FILE" is a special property, i.e., it shouldn't be set in a property
drawer. See (info "(org) Special properties").
> I am really happy with org-lint - thanks a lot. This makes working with
> org files much easier.
Thanks for all the feedback.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-22 19:08 ` Nicolas Goaziou
@ 2015-05-23 12:00 ` Rainer M Krug
2015-05-24 15:19 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-05-23 12:00 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 4332 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> 1) not identifying header argument with +
>> ,----
>> | #+PROPERTY: header-args+ :tangle no
>> `----
>>
>> results in
>>
>> ,----
>> | 87 high Unknown header argument ""
>> `----
>
> This should be fixed.
Thanks.
>
>> 2) not knowing header argument "file-ext" from R
>> ,----
>> | #+begin_src R :exports results :file-ext pdf :results graphics :width 8 :height 8
>> | plotSensMainEffAll(files)
>> | #+end_src
>> `----
>>
>> results in
>>
>> ,----
>> | 1691 high Unknown header argument "file-ext"
>> `----
>
> Fixed too.
Perfect - thanks.
>
>> 3) I am not to sure about this one, but in LaTeX labels of figures are
>> with the colon. Initially, I had #+LABEL: instead of #+NAME: but changed
>> it as one should use #+NAME instead of #+LABEL, but now I get the following:
>>
>> ,----
>> | #+CAPTION: The caption
>> | #+NAME: fig:sensDefault
>> | #+RESULTS: fig_sensDefault
>> | [[file:./output/fig_sensDefault.pdf]]
>> `----
>>
>> results in
>>
>> ,----
>> | 1686 high Name "fig:sensDefault" contains a colon; Babel cannot use it as input
>> `----
>>
>> I agree with the fact that Babel can not use it as input, but I do not
>> want to use it as input, only as a label in LaTeX for the figure?
>
> Then you can ignore safely this report.
Concerning ignoring: it would be nice to dynamically exclude certain
types of messages - i.e. hiding them from the results of the
linting. I don't think this is possible at
the moment?
I have literally about 100 names with a colon - so these messages are
overshadowing the really important ones.
>
>> According to the manual this should work:
>>
>> http://orgmode.org/manual/Images-and-tables.html:
>>
>> ,----
>> | #+CAPTION: This is the caption for the next figure link (or table)
>> | #+NAME: fig:SED-HR4049
>> | [[./img/a.jpg]]
>> `----
>>
>> So maybe check if this is part of a construct with a CAPTION or if it
>> really is used as an input somewhere?
>
> It is quite complicated to check if it is an input somewhere, e.g., it
> could be used as an input in another document.
True - haven't considered that.
>
>> 4) references where :FILE is a normal PROPERTY: (or isn't it?)
>>
>> ,----
>> | ** Koivusalo2002 - Snow processes in a forest clearing and in a coniferous forest
>> | :PROPERTIES:
>> | :TITLE: Snow processes in a forest clearing and in a coniferous forest
>> | :BTYPE: article
>> | :CUSTOM_ID: Koivusalo2002
>> | :AUTHOR: Koivusalo, H. and Kokkonen, T.
>> | :DOI: 10.1016/S0022-1694(02)00031-8
>> | :FILE: file:./Literature/Koivusalo_2002.pdf
>> | :ISSN: 00221694
>> | :JOURNAL: Journal of Hydrology
>> | :KEYWORDS: energy,forest,mathematical models,melt,snow,uxes
>> | :MENDELEY-GROUPS: Energy Balance,bibliography
>> | :MONTH: may
>> | :NUMBER: 1-4
>> | :PAGES: 145--164
>> | :URL: http://linkinghub.elsevier.com/retrieve/pii/S0022169402000318
>> | :VOLUME: 262
>> | :YEAR: 2002
>> | :END:
>> | [[file:Literature/Koivusalo2002.pdf]]
>> `----
>>
>> results in
>>
>> ,----
>> | 11221 high Special property "FILE" found in a properties drawer
>> `----
>
> "FILE" is a special property, i.e., it shouldn't be set in a property
> drawer. See (info "(org) Special properties").
OK - I'll throw it put then.
>
>> I am really happy with org-lint - thanks a lot. This makes working with
>> org files much easier.
>
> Thanks for all the feedback.
Pleasure - I found several undetected problems in my org file by using
the linting library.
Another question: When duplicate names are detected, would it be
possible to specify both (or more) line numbers in the warning? THis
would make finding them much easier.
Cheers,
Rainer
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-23 12:00 ` Rainer M Krug
@ 2015-05-24 15:19 ` Nicolas Goaziou
2015-05-24 15:52 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-24 15:19 UTC (permalink / raw)
To: Rainer M Krug; +Cc: emacs-orgmode
Rainer M Krug <Rainer@krugs.de> writes:
> Concerning ignoring: it would be nice to dynamically exclude certain
> types of messages - i.e. hiding them from the results of the
> linting. I don't think this is possible at
> the moment?
>
> I have literally about 100 names with a colon - so these messages are
> overshadowing the really important ones.
Done. Now, "h" hides reports from checker and point. "i" ignores them
altogether, which means they do not appear on subsequent refreshes.
> Another question: When duplicate names are detected, would it be
> possible to specify both (or more) line numbers in the warning? THis
> would make finding them much easier.
Done.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-24 15:19 ` Nicolas Goaziou
@ 2015-05-24 15:52 ` Rainer M Krug
2015-05-27 9:31 ` Andreas Leha
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-05-24 15:52 UTC (permalink / raw)
To: emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 1313 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> Concerning ignoring: it would be nice to dynamically exclude certain
>> types of messages - i.e. hiding them from the results of the
>> linting. I don't think this is possible at
>> the moment?
>>
>> I have literally about 100 names with a colon - so these messages are
>> overshadowing the really important ones.
>
> Done. Now, "h" hides reports from checker and point. "i" ignores them
> altogether, which means they do not appear on subsequent refreshes.
Sounds perfect - am really looking forward to trying it out on Tuesday.
>
>> Another question: When duplicate names are detected, would it be
>> possible to specify both (or more) line numbers in the warning? THis
>> would make finding them much easier.
>
> Done.
Perfect.
Cheers,
Rainer
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-24 15:52 ` Rainer M Krug
@ 2015-05-27 9:31 ` Andreas Leha
2015-05-27 10:49 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Andreas Leha @ 2015-05-27 9:31 UTC (permalink / raw)
To: emacs-orgmode
Hi Nicolas,
some more spurious warnings I get:
1. Captions with short version:
,----
| 1105 low Possible missing colon in keyword "#+caption[Data"
`----
2. header arguments from ob-latex:
,----
| 451 high Unknown header argument "packages"
| 451 high Unknown header argument "imoutoptions"
| 451 high Unknown header argument "iminoptions"
| 451 high Unknown header argument "imagemagick"
| 451 high Unknown header argument "fit"
`----
Best,
Andreas
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-05-27 9:31 ` Andreas Leha
@ 2015-05-27 10:49 ` Nicolas Goaziou
0 siblings, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-05-27 10:49 UTC (permalink / raw)
To: Andreas Leha; +Cc: emacs-orgmode
Hello,
Andreas Leha <andreas.leha@med.uni-goettingen.de> writes:
> some more spurious warnings I get:
>
>
> 1. Captions with short version:
>
> ,----
> | 1105 low Possible missing colon in keyword "#+caption[Data"
> `----
>
> 2. header arguments from ob-latex:
>
> ,----
> | 451 high Unknown header argument "packages"
> | 451 high Unknown header argument "imoutoptions"
> | 451 high Unknown header argument "iminoptions"
> | 451 high Unknown header argument "imagemagick"
> | 451 high Unknown header argument "fit"
> `----
Fixed. Thank you.
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
` (6 preceding siblings ...)
2015-05-19 13:32 ` Rainer M Krug
@ 2015-06-05 10:51 ` Rainer M Krug
2015-06-05 21:40 ` Nicolas Goaziou
7 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-06-05 10:51 UTC (permalink / raw)
To: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 3703 bytes --]
One more observation:
The link
,----
| [[file:__BOX__/Aerodynamic%20resistances.docx][file:./__BOX__/Aerodynamic resistances.docx]]
`----
causes the following warnings:
,----
| 9094 low Link to non-existent local file "__BOX__/Aerodynamic%20resistances.docx"
| 9094 low Link to non-existent local file "./__BOX__/Aerodynamic"
`----
although the file exists and the link works in org.
Cheers,
Rainer
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Hello,
>
> The following library implements linting for Org syntax. The sole public
> function is `org-lint', which see.
>
> Internally, the library defines a new structure: `org-lint-checker',
> with the following slots:
>
> - NAME: Unique check identifier, as a symbol. The check is done
> calling the function `org-lint-NAME' with one mandatory argument,
> the parse tree describing the current Org buffer. Such function
> calls are wrapped within a `save-excursion' and point is always at
> `point-min'. Its return value has to be an alist (POSITION MESSAGE)
> when POSITION refer to the buffer position of the error, as an
> integer, and MESSAGE is a strings describing the error.
>
> - DESCRIPTION: Summary about the check, as a string.
>
> - CATEGORIES: Categories relative to the check, as a list of symbol.
> They are used for filtering when calling `org-lint'. Checkers not
> explicitly associated to a category are collected in the `default'
> one.
>
> - TRUST: The trust level one can have in the check. It is either `low'
> or `high', depending on the heuristics implemented and the nature of
> the check. This has an indicative value only and is displayed along
> reports.
>
> All checks have to be listed in `org-lint--checkers'.
>
> Results are displayed in a special "*Org Lint*" buffer with a dedicated
> major mode, derived from `tabulated-list-mode'. In addition to the usual
> key-bindings inherited from it, "C-j" displays problematic line reported
> under point and "RET" jumps to it.
>
> Checks currently implemented are:
>
> - duplicates CUSTOM_ID properties
> - duplicate NAME values
> - duplicate targets
> - duplicate footnote definitions
> - orphaned affiliated keywords
> - obsolete affiliated keywords
> - missing language in src blocks
> - NAME values with a colon
> - wrong header arguments in src blocks
> - misuse of CATEGORY keyword
> - "coderef" links with unknown destination
> - "custom-id" links with unknown destination
> - "fuzzy" links with unknown destination
> - "id" links with unknown destination
> - links to non-existent local files
> - special properties in properties drawer
> - obsolete syntax for PROPERTIES drawers
> - missing definition for footnote references
> - missing reference for footnote definitions
> - non-footnote definitions in footnote section
> - probable invalid keywords
> - invalid blocks
> - probable incomplete drawers
> - obsolete QUOTE section
>
> Since it relies on lexical binding, `pcase' and `string-prefix-p', it
> cannot be added to Org 8.3, but can make it into Org 8.4, if deemed
> useful enough.
>
> Feedback welcome.
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-06-05 10:51 ` Rainer M Krug
@ 2015-06-05 21:40 ` Nicolas Goaziou
2015-06-06 14:44 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-06-05 21:40 UTC (permalink / raw)
To: Rainer M Krug; +Cc: Org Mode List
Rainer M Krug <Rainer@krugs.de> writes:
> The link
>
> ,----
> | [[file:__BOX__/Aerodynamic%20resistances.docx][file:./__BOX__/Aerodynamic resistances.docx]]
> `----
>
> causes the following warnings:
>
> ,----
> | 9094 low Link to non-existent local file "__BOX__/Aerodynamic%20resistances.docx"
Fixed. Thank you.
> | 9094 low Link to non-existent local file "./__BOX__/Aerodynamic"
> `----
>
> although the file exists and the link works in org.
Here, Org Lint is correct. Link's description is really a link to
a file, "./__BOX__/Aerodynamic", followed by a space, and
"resistances.docx" text.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-06-05 21:40 ` Nicolas Goaziou
@ 2015-06-06 14:44 ` Rainer M Krug
2015-06-06 23:22 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-06-06 14:44 UTC (permalink / raw)
To: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 1273 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> The link
>>
>> ,----
>> | [[file:__BOX__/Aerodynamic%20resistances.docx][file:./__BOX__/Aerodynamic resistances.docx]]
>> `----
>>
>> causes the following warnings:
>>
>> ,----
>> | 9094 low Link to non-existent local file "__BOX__/Aerodynamic%20resistances.docx"
>
> Fixed. Thank you.
Thanks.
>
>> | 9094 low Link to non-existent local file "./__BOX__/Aerodynamic"
>> `----
>>
>> although the file exists and the link works in org.
>
> Here, Org Lint is correct. Link's description is really a link to
> a file, "./__BOX__/Aerodynamic", followed by a space, and
> "resistances.docx" text.
But it is in the description part - shouldn't this be considered "normal
text" whatever it is?
Rainer
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-06-06 14:44 ` Rainer M Krug
@ 2015-06-06 23:22 ` Nicolas Goaziou
2015-06-08 7:50 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-06-06 23:22 UTC (permalink / raw)
To: Rainer M Krug; +Cc: Org Mode List
Rainer M Krug <Rainer@krugs.de> writes:
>> Here, Org Lint is correct. Link's description is really a link to
>> a file, "./__BOX__/Aerodynamic", followed by a space, and
>> "resistances.docx" text.
>
> But it is in the description part - shouldn't this be considered "normal
> text" whatever it is?
I wish it would. Unfortunately, Org has no proper image syntax, so we
have to support plain links (i.e, no brackets) in descriptions to get
image links.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-06-06 23:22 ` Nicolas Goaziou
@ 2015-06-08 7:50 ` Rainer M Krug
2015-06-09 7:30 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-06-08 7:50 UTC (permalink / raw)
To: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 1300 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>>> Here, Org Lint is correct. Link's description is really a link to
>>> a file, "./__BOX__/Aerodynamic", followed by a space, and
>>> "resistances.docx" text.
>>
>> But it is in the description part - shouldn't this be considered "normal
>> text" whatever it is?
>
> I wish it would. Unfortunately, Org has no proper image syntax, so we
> have to support plain links (i.e, no brackets) in descriptions to get
> image links.
OK - now I get it. The syntax implies that I want to display the image
located there as the descriptor.
Would it be possible for org-lint to give a more direct warning that this
link is in the description and not the link itself?
Thanks for your patience - I am learning a lot about org by using org-lint!
Rainer
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-06-08 7:50 ` Rainer M Krug
@ 2015-06-09 7:30 ` Nicolas Goaziou
2015-06-09 7:50 ` Rainer M Krug
0 siblings, 1 reply; 53+ messages in thread
From: Nicolas Goaziou @ 2015-06-09 7:30 UTC (permalink / raw)
To: Rainer M Krug; +Cc: Org Mode List
Rainer M Krug <Rainer@krugs.de> writes:
> OK - now I get it. The syntax implies that I want to display the image
> located there as the descriptor.
Correct.
> Would it be possible for org-lint to give a more direct warning that this
> link is in the description and not the link itself?
Could you suggest an appropriate warning?
Thank you.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-06-09 7:30 ` Nicolas Goaziou
@ 2015-06-09 7:50 ` Rainer M Krug
2015-06-16 21:54 ` Nicolas Goaziou
0 siblings, 1 reply; 53+ messages in thread
From: Rainer M Krug @ 2015-06-09 7:50 UTC (permalink / raw)
To: Org Mode List
[-- Attachment #1: Type: text/plain, Size: 1173 bytes --]
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Rainer M Krug <Rainer@krugs.de> writes:
>
>> OK - now I get it. The syntax implies that I want to display the image
>> located there as the descriptor.
>
> Correct.
>
>> Would it be possible for org-lint to give a more direct warning that this
>> link is in the description and not the link itself?
>
> Could you suggest an appropriate warning?
something along the line of "Link to non-existent local file "..." in
the description part" would make clear that it is ion the description of
a link.
And if the non-existent link is in the link part, the other could be
"Link to non-existent local file "..." in the link part"
Cheers,
Rainer
>
> Thank you.
>
>
> Regards,
--
Rainer M. Krug, PhD (Conservation Ecology, SUN), MSc (Conservation Biology, UCT), Dipl. Phys. (Germany)
Centre of Excellence for Invasion Biology
Stellenbosch University
South Africa
Tel : +33 - (0)9 53 10 27 44
Cell: +33 - (0)6 85 62 59 98
Fax : +33 - (0)9 58 10 27 44
Fax (D): +49 - (0)3 21 21 25 22 44
email: Rainer@krugs.de
Skype: RMkrug
PGP: 0x0F52F982
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 494 bytes --]
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [RFC] Org linting library
2015-06-09 7:50 ` Rainer M Krug
@ 2015-06-16 21:54 ` Nicolas Goaziou
0 siblings, 0 replies; 53+ messages in thread
From: Nicolas Goaziou @ 2015-06-16 21:54 UTC (permalink / raw)
To: Rainer M Krug; +Cc: Org Mode List
Rainer M Krug <Rainer@krugs.de> writes:
> something along the line of "Link to non-existent local file "..." in
> the description part" would make clear that it is ion the description of
> a link.
Done. Thanks.
Regards,
^ permalink raw reply [flat|nested] 53+ messages in thread
end of thread, other threads:[~2015-06-16 21:53 UTC | newest]
Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-19 13:31 [RFC] Org linting library Nicolas Goaziou
2015-04-19 14:23 ` Rasmus
2015-04-19 16:24 ` Nicolas Goaziou
2015-04-19 19:32 ` Marco Wahl
2015-04-20 10:42 ` Nicolas Goaziou
2015-04-20 2:15 ` Charles C. Berry
2015-04-20 9:12 ` Nicolas Goaziou
2015-04-22 19:27 ` Nicolas Goaziou
2015-04-22 19:31 ` Sebastien Vauban
2015-04-22 19:40 ` Nicolas Goaziou
2015-04-23 10:47 ` Eric Abrahamsen
2015-04-23 16:25 ` Sebastien Vauban
2015-04-26 12:50 ` Nicolas Goaziou
2015-04-27 15:22 ` Doug Lewan
2015-05-19 11:54 ` Andreas Leha
2015-05-19 13:39 ` Nicolas Goaziou
2015-05-19 14:54 ` Andreas Leha
2015-05-19 19:09 ` Nicolas Goaziou
2015-05-19 20:02 ` Andreas Leha
2015-05-19 21:03 ` Nicolas Goaziou
2015-05-19 21:10 ` Andreas Leha
2015-05-19 21:26 ` Nicolas Goaziou
2015-05-19 21:35 ` Andreas Leha
2015-05-19 13:32 ` Rainer M Krug
2015-05-19 13:43 ` Andreas Leha
2015-05-20 15:01 ` Rainer M Krug
2015-05-20 15:08 ` Rainer M Krug
2015-05-20 15:24 ` Rainer M Krug
2015-05-20 20:42 ` Andreas Leha
2015-05-20 21:15 ` Rainer M Krug
2015-05-20 21:46 ` Nicolas Goaziou
2015-05-21 8:40 ` Rainer M Krug
2015-05-21 16:24 ` Nicolas Goaziou
2015-05-21 18:18 ` Rainer M Krug
2015-05-21 18:23 ` Rainer M Krug
2015-05-21 18:30 ` Rainer M Krug
2015-05-21 21:53 ` Nicolas Goaziou
2015-05-22 8:10 ` Rainer M Krug
2015-05-22 19:08 ` Nicolas Goaziou
2015-05-23 12:00 ` Rainer M Krug
2015-05-24 15:19 ` Nicolas Goaziou
2015-05-24 15:52 ` Rainer M Krug
2015-05-27 9:31 ` Andreas Leha
2015-05-27 10:49 ` Nicolas Goaziou
2015-05-19 13:47 ` Nicolas Goaziou
2015-06-05 10:51 ` Rainer M Krug
2015-06-05 21:40 ` Nicolas Goaziou
2015-06-06 14:44 ` Rainer M Krug
2015-06-06 23:22 ` Nicolas Goaziou
2015-06-08 7:50 ` Rainer M Krug
2015-06-09 7:30 ` Nicolas Goaziou
2015-06-09 7:50 ` Rainer M Krug
2015-06-16 21:54 ` Nicolas Goaziou
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.