Closed ouboub closed 3 years ago
Either using latex $\boxtimes$ or UTF8 ☒
I will install this patch sometime in the future ...
(custom-set-variables
'(org-entities-user
'(
("boxminus" "\\boxminus" t "⊟" "[-]" "[-]" "⊟")
("boxtimes" "\\boxtimes" t "⊠" "[x]" "[x]" "⊠")
("square" "\\square" t "□" "[ ]" "[ ]" "□"))))
(defun org-odt--checkbox (item)
"Return check-box string associated to ITEM."
(let ((checkbox (org-element-property :checkbox item)))
(if (not checkbox) ""
(format "<text:span text:style-name=\"%s\">%s </text:span>"
"OrgCode" (cl-case checkbox
;; ⊠ ⊠ ⊠ ⊠ ⊠ SQUARED TIMES
(on (or (nth 6 (org-entity-get "boxtimes"))
(on "[✓]") ; CHECK MARK
))
;; □ □ □ □ □ □ WHITE SQUARE
(off (or (nth 6 (org-entity-get "square"))
(off "[ ]")))
;; ⊟ ⊟ ⊟ ⊟ ⊟ SQUARED MINUS
(trans (or (nth 6 (org-entity-get "boxminus"))
(trans "[-]"))))))))
entities
allows for more flexibilityUse of entities
allows one to choose whatever checkboxes one wants. There doesn't seem to be a "consistent" set of unicode symbols that allow for "tristate" checkboxes.
Instead of the suggestion above one can go with, for example, these set of characters
🗷⮽🞏
character: 🗷 (displayed as 🗷) (codepoint 128503, #o372767, #x1f5f7)
charset: unicode (Unicode (ISO10646))
code point in charset: 0x1F5F7
script: symbol
syntax: w which means: word
category: .:Base
to input: type "C-x 8 RET 1f5f7" or "C-x 8 RET BALLOT BOX WITH BOLD SCRIPT X"
character: ⮽ (displayed as ⮽) (codepoint 11197, #o25675, #x2bbd)
charset: unicode-bmp (Unicode Basic Multilingual Plane (U+0000..U+FFFF))
code point in charset: 0x2BBD
script: symbol
syntax: _ which means: symbol
category: .:Base
to input: type "C-x 8 RET 2bbd" or "C-x 8 RET BALLOT BOX WITH LIGHT X"
character: 🞏 (displayed as 🞏) (codepoint 128911, #o373617, #x1f78f)
charset: unicode (Unicode (ISO10646))
code point in charset: 0x1F78F
script: symbol
syntax: w which means: word
category: .:Base
to input: type "C-x 8 RET 1f78f" or "C-x 8 RET MEDIUM WHITE SQUARE"
- [-] test
- [ ] one
- [X] two
- \boxminus test
- \square one
- \boxtimes two
FWIW, this is how tristate checkbox controls are rendered in LibreOffice
Re-opening this issue ...
TLDR: Use of checkbox control--instead of unicode characters--cannot be easily accomplished with what is right now in the ox-odt.el
.
Two comments:
1. Can that patch easily applied to the clone github repository? I
might give it a try for testing.
2. I realized that I should add, that I need to generate an odt
document, in which checkboxes are placed in tables, a feature
that is not supported by org mode as of today, unfortunately. So
I think that cannot be solved by any exporter.
I have improved typesetting of checkboxes in https://github.com/kjambunathan/org-mode-ox-odt/commit/33eb2bc464affbfdf651611c9f74a572db09544a. See the commit log / diff for details.
#+options: e:t
#+begin_src emacs-lisp :results silent :exports none
(dolist (new-entity
'(
;; ("name" "LaTeX" "LaTeX mathp" "HTML" "ASCII" "Latin1" "utf-8")
("checkboxon" "\\boxtimes" t "🗷" "[x]" "[x]" "🗷") ; 🗷 - BALLOT BOX WITH BOLD SCRIPT X
("checkboxoff" "\\square" t "🞏" "[ ]" "[ ]" "🞏") ; 🞏 - MEDIUM WHITE SQUARE
("checkboxwip" "\\boxminus" t "⮽" "[-]" "[-]" "⮽" ) ; ⮽ - BALLOT BOX WITH LIGHT X
))
(map-delete org-entities-user (car new-entity))
(customize-set-variable 'org-entities-user (cons new-entity org-entities-user))
(customize-save-variable 'org-entities-user org-entities-user))
#+end_src
- [-] Organize party [1/4]
- [-] call people [2/3]
- [ ] Peter
- [X] Sarah
- [X] Sam
- [ ] order food
- [ ] think about what music to play
- [X] talk to the neighbors
- \checkboxwip Organize party
- \checkboxwip call people
- \checkboxoff Peter
- \checkboxon Sarah
- \checkboxon Sam
- \checkboxoff order food
- \checkboxoff think about what music to play
- \checkboxon talk to the neighbors
This is the how the exported documented looks like:
- I realized that I should add, that I need to generate an odt document, in which checkboxes are placed in tables, a feature that is not supported by org mode as of today, unfortunately. So I think that cannot be solved by any exporter.
The context is this
shrink table in columnmode view (poor man's issue system)
Let me help you define and (partially) solve the problem for you.
With headlines like this
instead of generating a colview table like this
you can generate a colview table like this
or a checklist like this
The zip file below has the needed recipes.
colview-as-checklist-as-opposed-to-a-table.zip
Btw, as the .org
file mentions the solution provided by Marco Wahl in https://lists.gnu.org/archive/html/emacs-orgmode/2021-09/msg00408.html will not work when the dblock has affiliated keywords like caption.
You will have better luck if you reword your original request along the following lines ... The :format
field of columnview dblock, merely collects the fields. What you need is a second level formatter that emits a formatted string with the collected fields. i.e., if the fields separated by |
you get a table, instead if they are preceded by -
and separated by ` you get a checklist. The second level formatter would allow specification of the "constant" strings in the formatter. The current implementation only looks for
%STUFF` and skips over other "constant" strings. (It is difficult to explain, but you can infer what I mean.)
(I will leave you with this half-baked response. My focus is ODT exporter. Anything outside of it is not of any interest to me ... I hope I have shared enough information so that you can build upon what I have offered you.)
- I realized that I should add, that I need to generate an odt document, in which checkboxes are placed in tables, a feature that is not supported by org mode as of today, unfortunately. So I think that cannot be solved by any exporter.
You provide little context and little in way of what you want.
With such a request it is unlikely that someone (including me) would step up to define and solve the problem for you. You probably know this. You have been in FLOSS lists much longer than I have been. So, next time, please provide a better context and definition of what you want. I will be more than happy to help.
#+options: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
#+options: author:t broken-links:mark c:nil creator:nil
#+options: d:(not "LOGBOOK") date:t e:t email:nil f:t inline:t num:t
#+options: p:nil pri:nil prop:nil stat:t tags:t tasks:t tex:t
#+options: timestamp:t title:t toc:t todo:nil |:t
#+title: checkbox-2
#+date: <2021-10-02 Sat>
#+author: Jambunathan K
#+email: kjambunathan@debian
#+language: en
#+select_tags: export
#+exclude_tags: noexport
#+creator: Emacs 28.0.50 (Org mode 9.4.4)
#+STARTUP: align
#+STARTUP: shrink
* A Useful Hack
Set TODO keywords as Checkbox states
This will be useful in [[*Columnview as a checklist][Columnview as a checklist]]
#+begin_src emacs-lisp :results silent :exports code
(setq org-todo-keywords
'((sequence "[ ]" "[-]" "|" "[X]" )))
(org-update-all-dblocks)
(call-interactively 'save-buffer)
#+end_src
* [ ] Top-level issue [2/4]
:PROPERTIES:
:COLUMNS: %50ITEM(Problem) %10Is(Issue Nr) %7TODO(TODO) %26TAGS(Which) %17Date(Date)
:ID: Issues
:COOKIE_DATA: todo recursive
:END:
** [X] First child issue first child issue first child issue
:PROPERTIES:
:Date: <2021-09-25 Sat>
:Is: #9
:URL: https://github.com/kjambunathan/org-mode-ox-odt/issues/99
:END:
** [X] Second child issue second child issue second child issue second child issue
:PROPERTIES:
:Date: <2021-09-25 Sat>
:Is: NA
:URL: https://lists.gnu.org/archive/html/emacs-orgmode/2021-09/msg00321.html
:END:
** [-] Third child issue third child issue third child issue third child issue
:PROPERTIES:
:Date: <2021-09-25 sáb>
:Is: #9
:URL:
:END:
** [ ] Fourth child issue fourth child issue fourth child issue fourth child issue
:PROPERTIES:
:Date: <2021-09-25 sáb>
:Is: #9
:URL:
:END:
* Column Views
** Stock Columnview
#+BEGIN: columnview :id Issues :hlines 2 :skip-empty-rows t :indent nil
#+CAPTION: Stock columnview
| Problem | Issue Nr | TODO | Which | Date |
|-----------------------------------------------------------------------------+----------+------+-------+------------------|
| Top-level issue | | [ ] | | |
|-----------------------------------------------------------------------------+----------+------+-------+------------------|
| First child issue first child issue first child issue | #9 | [X] | | <2021-09-25 Sat> |
|-----------------------------------------------------------------------------+----------+------+-------+------------------|
| Second child issue second child issue second child issue second child issue | NA | [X] | | <2021-09-25 Sat> |
|-----------------------------------------------------------------------------+----------+------+-------+------------------|
| Third child issue third child issue third child issue third child issue | #9 | [-] | | <2021-09-25 sáb> |
|-----------------------------------------------------------------------------+----------+------+-------+------------------|
| Fourth child issue fourth child issue fourth child issue fourth child issue | #9 | [ ] | | <2021-09-25 sáb> |
#+END:
** COMMENT Columnview with Shrink
The code below is from [this message](https://lists.gnu.org/archive/html/emacs-orgmode/2021-09/msg00408.html).
#+name: columnview2
#+begin_src emacs-lisp :results silent :exports none
(defun org-dblock-write:columnview2 (params)
"Write the column view table.
Like org-dblock-write:columnview but write a line with shrink widths
taken from the
column view format.
PARAMS is the same as in `org-dblock-write:columnview'."
(insert (format "|%s|\n"
(mapconcat
(lambda (x) (concat "<" (number-to-string x) ">"))
(mapcar (lambda (x) (nth 2 x))
(org-columns-compile-format
(plist-get params
:format)))
"|")))
(org-dblock-write:columnview params))
#+end_src
~org-dblock-write:columnview2~ as defined above doesn't allow a
caption to be added to a dynamic block.
The dynamic block below is OK
#+BEGIN: columnview2 :id Issues :hlines 2 :skip-empty-rows t :indent nil :format "%10ITEM(Problem) %5Is(Issue) %12TODO %12Date"
| <10> | <5> | <12> | <12> |
| Problem | Issue | TODO | Date |
|-----------------------------------------------------------------------------+-------+------+------------------|
| Top-level issue | | [ ] | |
|-----------------------------------------------------------------------------+-------+------+------------------|
| First child issue first child issue first child issue | #9 | [X] | <2021-09-25 Sat> |
|-----------------------------------------------------------------------------+-------+------+------------------|
| Second child issue second child issue second child issue second child issue | NA | [X] | <2021-09-25 Sat> |
|-----------------------------------------------------------------------------+-------+------+------------------|
| Third child issue third child issue third child issue third child issue | #9 | [-] | <2021-09-25 sáb> |
|-----------------------------------------------------------------------------+-------+------+------------------|
| Fourth child issue fourth child issue fourth child issue fourth child issue | #9 | [ ] | <2021-09-25 sáb> |
#+END:
... but not this one
# #+BEGIN: columnview2 :id Issues :hlines 2 :skip-empty-rows t :indent nil :format "%10ITEM(Problem) %5Is(Issue) %12TODO %12Date"
# #+CAPTION: Columnview with Shrink
# | <10> | <5> | <12> | <12> |
# | Problem | Issue | TODO | Date |
# |-----------------------------------------------------------------------------+-------+------+------------------|
# | Top-level issue | | [ ] | |
# |-----------------------------------------------------------------------------+-------+------+------------------|
# | First child issue first child issue first child issue | #9 | [X] | <2021-09-25 Sat> |
# |-----------------------------------------------------------------------------+-------+------+------------------|
# | Second child issue second child issue second child issue second child issue | NA | [X] | <2021-09-25 Sat> |
# |-----------------------------------------------------------------------------+-------+------+------------------|
# | Third child issue third child issue third child issue third child issue | #9 | [-] | <2021-09-25 sáb> |
# |-----------------------------------------------------------------------------+-------+------+------------------|
# | Fourth child issue fourth child issue fourth child issue fourth child issue | #9 | [ ] | <2021-09-25 sáb> |
# #+END:
** Columnview with alignment, width and colgroups
#+CAPTION: Column view with widths, alignment, colgroups
#+name: columnview3
#+begin_src emacs-lisp :results silent :exports none
(defun org-dblock-write:columnview3 (params)
"Write the column view table.
Use `:preamble'. Ignore the widths in `:format' string."
(when (plist-get params :preamble)
(insert (plist-get params :preamble) "\n"))
(org-dblock-write:columnview params))
#+end_src
The function above has same problems wrt caption.
#+BEGIN: columnview3 :id Issues :hlines 2 :skip-empty-rows t :indent nil :format "%12TODO %10ITEM(Problem) %5Is(Issue) %12Date" :preamble "| <r2> | <l10> | <5> | <12> |\n| / | | < | |"
| <r2> | <l10> | <5> | <12> |
| / | | < | |
| TODO | Problem | Issue | Date |
|------+-----------------------------------------------------------------------------+-------+------------------|
| [ ] | Top-level issue | | |
|------+-----------------------------------------------------------------------------+-------+------------------|
| [X] | First child issue first child issue first child issue | #9 | <2021-09-25 Sat> |
|------+-----------------------------------------------------------------------------+-------+------------------|
| [X] | Second child issue second child issue second child issue second child issue | NA | <2021-09-25 Sat> |
|------+-----------------------------------------------------------------------------+-------+------------------|
| [-] | Third child issue third child issue third child issue third child issue | #9 | <2021-09-25 sáb> |
|------+-----------------------------------------------------------------------------+-------+------------------|
| [ ] | Fourth child issue fourth child issue fourth child issue fourth child issue | #9 | <2021-09-25 sáb> |
#+END:
** Columnview as a checklist
#+CAPTION: Column view as proper as checklist
#+name: checklist
#+begin_src emacs-lisp :results silent :exports none
(defun org-dblock-write:checklist (params)
"Write the column view table.
PARAMS is a property list of parameters:
`:id' (mandatory)
The ID property of the entry where the columns view should be
built. When the symbol `local', call locally. When `global'
call column view with the cursor at the beginning of the
buffer (usually this means that the whole buffer switches to
column view). When \"file:path/to/file.org\", invoke column
view at the start of that file. Otherwise, the ID is located
using `org-id-find'.
`:exclude-tags'
List of tags to exclude from column view table.
`:format'
When non-nil, specify the column view format to use.
`:hlines'
When non-nil, insert a hline before each item. When
a number, insert a hline before each level inferior or equal
to that number.
`:indent'
When non-nil, indent each ITEM field according to its level.
`:match'
When set to a string, use this as a tags/property match filter.
`:maxlevel'
When set to a number, don't capture headlines below this level.
`:skip-empty-rows'
When non-nil, skip rows where all specifiers other than ITEM
are empty.
`:skip-header'
When non-nil, skip the header."
(let ((table
(let ((id (plist-get params :id))
view-file view-pos)
(pcase id
(`global nil)
((or `local `nil) (setq view-pos (point)))
((and (let id-string (format "%s" id))
(guard (string-match "^file:\\(.*\\)" id-string)))
(setq view-file (match-string-no-properties 1 id-string))
(unless (file-exists-p view-file)
(user-error "No such file: %S" id-string)))
((and (let idpos (org-find-entry-with-id id)) (guard idpos))
(setq view-pos idpos))
((let `(,filename . ,position) (org-id-find id))
(setq view-file filename)
(setq view-pos position))
(_ (user-error "Cannot find entry with :ID: %s" id)))
(with-current-buffer (if view-file (get-file-buffer view-file)
(current-buffer))
(org-with-wide-buffer
(when view-pos (goto-char view-pos))
(org-columns--capture-view (plist-get params :maxlevel)
(plist-get params :match)
(plist-get params :skip-empty-rows)
(plist-get params :exclude-tags)
(plist-get params :format)
view-pos))))))
(when table
;; Prune level information from the table. Also normalize
;; headings: remove stars, add indentation entities, if
;; required, and possibly precede some of them with a horizontal
;; rule.
(let ((item-index
(let ((p (assoc "ITEM" org-columns-current-fmt-compiled)))
(and p (cl-position p
org-columns-current-fmt-compiled
:test #'equal))))
(hlines (plist-get params :hlines))
(indent (plist-get params :indent))
new-table)
;; Copy header and first rule.
;; (push (pop table) new-table)
;; (push (pop table) new-table)
(cond
((plist-get params :skip-header)
(pop table)
(pop table))
(t
(push (pop table) new-table)
(push (pop table) new-table)))
(dolist (row table (setq table (nreverse new-table)))
(let ((level (car row)))
(when (and (not (eq (car new-table) 'hline))
(or (eq hlines t)
(and (numberp hlines) (<= level hlines))))
(push 'hline new-table))
;; (when item-index
;; (let ((item (org-columns--clean-item (nth item-index (cdr row)))))
;; (setf (nth item-index (cdr row))
;; (if (and indent (> level 1))
;; (concat "\\_" (make-string (* 2 (1- level)) ?\s) item)
;; item))))
(setcar (cdr row) (format "%s- %s" (make-string (* 2 (1- level)) ?\s) (cadr row)))
(push (cdr row) new-table))))
(let ((content-lines (org-split-string (plist-get params :content) "\n")))
;; Insert affiliated keywords before the table.
(when content-lines
(while (string-match-p "\\`[ \t]*#\\+" (car content-lines))
(insert (pop content-lines) "\n")))
(save-excursion
;; Insert table at point.
(insert
(mapconcat (lambda (row)
(if (eq row 'hline) ""
(format "%s" (mapconcat #'identity row " "))))
table
"\n")))))))
#+end_src
*Column view as proper as checklist*
#+BEGIN: checklist :id Issues :skip-header t :hlines 2 :skip-empty-rows t :indent nil :format "%12TODO %10ITEM(Problem) %5Is(Issue) %12Date"
- [ ] Top-level issue [2/4]
- [X] First child issue first child issue first child issue #9 <2021-09-25 Sat>
- [X] Second child issue second child issue second child issue second child issue NA <2021-09-25 Sat>
- [-] Third child issue third child issue third child issue third child issue #9 <2021-09-25 sáb>
- [ ] Fourth child issue fourth child issue fourth child issue fourth child issue #9 <2021-09-25 sáb>
#+END:
# Local Variables:
# eval: (menu-bar--toggle-truncate-long-lines)
# End:
If you haven't already noticed ... the snippet below is the one that will help you generate "first class" checklists from the colview definition.
A Useful Hack
Set TODO keywords as Checkbox states
This will be useful in [[*Columnview as a checklist][Columnview as a checklist]]
(setq org-todo-keywords
'((sequence "[ ]" "[-]" "|" "[X]" )))
You will have better luck if you reword your original request along the following lines ...
(I think) you may also need a way to "map" todo keywords like TODO, DONE etc. to their equivalent "ascii" or "ballot box" versions for export purposes.
Thanks very much for your help, I really appreciate this quick, detailed and helpful responses. Just allow me to clarify two things.
Now with your code I might try to write it as org checkboxes and try to export it, I am however not completely sure that it will work. In any case you answer is very useful for the question I brought up on the org-mode list regards UB
Fix available in ox-odt-9.3.7.327.tar
or later versions.
Hi
Any idea how to export checkboxes to odt?
I mean not just simply having [ ] in the odt document but having them translated as actual boxes.
Thanks and regards
Uwe Brauer