Projects About AlBasmala
build status

org-special-block-extras: demos that are tests, rather than docs

Article image
  

Ξ  

⭐ The code lives at github.com/alhassy/org-special-block-extras —star it, or discuss it there!

1. badge

﴾What You Write﴿
1. It works when all 5 arguments are provided

   badge:Let_me_google_that|for_you!|orange|https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir

2. It works when we use [ [ link ] ] syntax with generous spaces and newlines

   [[badge: Let me google that | for you! | orange |
         https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir]]

3. It works when only the first 2 arguments are provided;
   asterisks are passed unaltered into the first argument
   
   badge:Let_me_*not*_google_that|for_you

4. It works sans a URL, yet with a logo; Org's own <<key>> beside it is a permalink to here

   <<key>> badge:key|value|informational||Elixir

5. We can use spaces, commas, dashes, and percentage symbols in the first argument

   badge:example_with_spaces,_-,_and_%|points_right_here|orange

6. It works when only first 2 arguments are given: Default colour & logo are green & no logo shown

   badge:key|value

7. When only a key is provided, the value slot is shown as an empty green stub

   badge:key

8. When only a value is provided, only the value is shown in a default green
   ---no stub for the missing key, yay

   badge:|value

9. It's only a green stub when provided with an empty key and empty value

   badge:||green

10. It's only a green stub when we use no options at all

   [[badge:]]
﴾What You Get﴿
  1. It works when all 5 arguments are provided

  2. It works when we use [ [ link ] ] syntax with generous spaces and newlines

  3. It works when only the first 2 arguments are provided; asterisks are passed unaltered into the first argument

  4. It works sans a URL, yet with a logo; Org's own beside it is a permalink to here

  5. We can use spaces, commas, dashes, and percentage symbols in the first argument

  6. It works when only first 2 arguments are given: Default colour & logo are green & no logo shown

  7. When only a key is provided, the value slot is shown as an empty green stub

  8. When only a value is provided, only the value is shown in a default green —no stub for the missing key, yay

  9. It's only a green stub when provided with an empty key and empty value

  10. It's only a green stub when we use no options at all


﴾How It’s Implemented﴿
(org-make-badge "badge")

2. calc

﴾What You Write﴿
#+begin_math
  x
={ Explanation of why $x \;=\; y$.
   Actually, let me explain:
   \[   x
      ={ hint 1 } x′
      ={ hint 2 } y \]
   Words may follow a nested calculation.
 }
  y
≤{ Explanation of why $y \;\leq\; z$
   # Explain it more; this comment is absent from the export ;-)
 }
  z
#+end_math
﴾What You Get﴿
\begin{align*} & x \\ = & \quad \class{tooltip osbe-tip-hint osbe-hint}{\class{osbe-hint-body}{{\color[RGB]{128,0,0} \left[ \begin{array}{@{}l@{}} \text{Explanation of why $x \;=\; y$.} \\ \text{Actually, let me explain:} \\ \begin{aligned}[t] & x \\ = & \quad \class{tooltip osbe-tip-hint osbe-hint}{\class{osbe-hint-body}{{\color[RGB]{128,0,0} \left[ \text{hint 1} \right.}}\class{osbe-hint-fold}{{\color[RGB]{128,0,0} [\,\cdots\,]}}} \\ & x′ \\ = & \quad \class{tooltip osbe-tip-hint osbe-hint}{\class{osbe-hint-body}{{\color[RGB]{128,0,0} \left[ \text{hint 2} \right.}}\class{osbe-hint-fold}{{\color[RGB]{128,0,0} [\,\cdots\,]}}} \\ & y \end{aligned} \\ \text{Words may follow a nested calculation.} \end{array} \right.}}\class{osbe-hint-fold}{{\color[RGB]{128,0,0} [\,\cdots\,]}}} \notag \\ & y \\ ≤ & \quad \class{tooltip osbe-tip-hint osbe-hint}{\class{osbe-hint-body}{{\color[RGB]{128,0,0} \left[ \text{Explanation of why $y \;\leq\; z$} \right.}}\class{osbe-hint-fold}{{\color[RGB]{128,0,0} [\,\cdots\,]}}} \notag \\ & z \end{align*}

3. kbd

﴾What You Write﴿
1. It becomes <kbd> tags, but final symbol non-ascii *may* be ignored

   kbd:C-u_80_-∀

2. [ [ It ] ] becomes <kbd> tags

   [[kbd:C-u_80_-]]

3. Using syntax <it> becomes <kbd> tags, and surrounding space is trimmed

   <kbd: C-u 80 - >

4. It has a tooltip documenting the underlying Lisp function, when possible

   <kbd: M-s h .>
﴾What You Get﴿
  1. It becomes <kbd> tags, but final symbol non-ascii may be ignored

    C-u 80 -∀

  2. [ [ It ] ] becomes <kbd> tags

    C-u 80 -

  3. Using syntax <it> becomes <kbd> tags, and surrounding space is trimmed

    C-u 80 -

  4. It has a tooltip documenting the underlying Lisp function, when possible

    M-s h .


﴾How It’s Implemented﴿
(org-deflink kbd (keys &optional description backend)
  "Show keysequence KEYS in a nice grey button-like font, along with a tooltip of its documentation, if any.

Such links do not get folded in [[bracket]] style, and are rendered as buttons within Emacs; clicking one
runs its keys, so readers may try them out.  Keys may run any command, so we first ask, as `elisp' links
do, via `org-link-elisp-confirm-function'.

Moreover, KEYS may use ‘_’ in-lieu of spaces or [[bracket]] link notation.

Examples:
    [[kbd:C-x C-s]]
  ≈ <kbd: C-x C-s>
  ≈ kbd:C-x_C-s"
  :display 'full
  :manual "#nice-keystroke-renditions"
  :let (the-label  (s-trim (s-replace "_" " " keys))
        lisp-func  (ignore-errors (key-binding (kbd the-label)))
        tooltip    (or description (ignore-errors (documentation lisp-func)) "")
        tooltip?   (not (equal tooltip ""))
        style      (if tooltip? "border-color: red" "")
        keystrokes (progn (org-html-head-require 'org--kbd-html-head)
                          (format "<kbd style=\"%s\">%s</kbd>" style the-label)))
  ;; The description is always nil when it comes to deciding the :face.
  :face (list :inherit 'custom-button :box (if tooltip? "red" t))
  :help-echo (format "%s ∷ %s\n%s\n\nClick to run these keys." the-label (or lisp-func "") tooltip)
  :follow (org--kbd-run the-label)
  :export (cond ((equal backend 'latex) (format "\\texttt{%s}" the-label))
                ;; The style is to remove the underlining caused by <abbr>.
                (tooltip? (org--html-tooltip (format "%s ∷ %s\n%s" the-label (or lisp-func "") tooltip) keystrokes
                                             :plain "border: none; text-decoration: none;"))
                (t keystrokes)))

4. solution

﴾What You Write﴿
What is the name of Prophet Yusuf's father?

Hint: The father's name also starts with `y`.

#+begin_solution
Yacoub
#+end_solution
﴾What You Get﴿

What is the name of Prophet Yusuf's father?

Hint: The father's name also starts with `y`.

Solution

Did you actually try? Maybe see the ‘hints’ above!

Solution, for real

Yacoub


﴾How It’s Implemented﴿
(org-defblock solution
              (&optional (title "Solution")
               &key (reprimand "Did you actually try? Maybe see the ‘hints’ above!") (really "Solution, for real")
               &allow-other-keys :manual "#Boxed-Text" &context raw-contents)
              "Show the answers to a problem, but with a reprimand in case no attempt was made."
              (org-thread-blockcall raw-contents
                                    (details really :title-color "red")
                                    (box reprimand :background-color "blue")
                                    (details title)))

5. spoiler

﴾What You Write﴿
The ~spoiler~ block is for “fill in the blanks” or “guess, and hover
to see the results” style of exposition.

#+begin_spoiler
((Yusuf)) said to his father ((Yacoub)), /“O my father, indeed I have seen
((eleven stars)) and ((the sun and the moon)); I saw them prostrating to me.”/
#+end_spoiler

There are also options for the left delimiter of a hidden item, the right delimiter,
and the color of the hidden item. These default to ~grey, ((, ))~ respectively.

#+begin_spoiler orange :left "[" :right "]"
[Yusuf] said to his father [Yacoub], /“O my father, indeed I have seen
[eleven stars] and [the sun and the moon]; I saw them prostrating to me.”/
#+end_spoiler
﴾What You Get﴿

The spoiler block is for “fill in the blanks” or “guess, and hover to see the results” style of exposition.

Yusuf said to his father Yacoub , “O my father, indeed I have seen eleven stars and the sun and the moon ; I saw them prostrating to me.”

There are also options for the left delimiter of a hidden item, the right delimiter, and the color of the hidden item. These default to grey, ((, )) respectively.

Yusuf said to his father Yacoub , “O my father, indeed I have seen eleven stars and the sun and the moon ; I saw them prostrating to me.”


﴾How It’s Implemented﴿
(org-defblock spoiler (&optional (color "grey") &key (left "((") (right "))") &allow-other-keys :manual "#Boxed-Text"
                      &context backend raw-contents contents)
              "Hide text enclosed in double parens ((like this)) as if it were spoilers.
   LEFT and RIGHT may be other kinds of delimiters.
   The main argument, COLOR, indicates which color to use.

For LaTeX, this becomes “fill in the blanks”, with the answers
in the footnotes; for Markdown, whose renderers strip <style>, numbered
blanks with the answers folded away beneath them."
              (cond
               ((org-export-markdown-p)
                (let* ((answers nil)
                       (blanked (replace-regexp-in-string
                                 (concat (regexp-quote left) "\\(.*?\\)" (regexp-quote right))
                                 (lambda (it)
                                   (push (match-string 1 it) answers)
                                   (format "@@html:<ins>&emsp;%s&emsp;</ins>@@" (length answers)))
                                 raw-contents t t)))
                  (org-parse (format "%s\n\n#+html: <details><summary>Answers</summary>\n\n%s\n\n#+html: </details>"
                                     blanked
                                     (s-join "\n" (--map-indexed (format "%s. %s" (1+ it-index) it) (reverse answers)))))))
               ((equal backend 'latex)
                (s-replace-regexp
                 (concat (regexp-quote left) "\\(.*?\\)" (regexp-quote right))
                 "@@latex:\\\\fbox{\\\\phantom{\\1}}\\\\footnote{\\1}@@"
                 contents))
               (t
                ;; The styling depends only on COLOR, so a class per colour serves every spoiler of that colour.
                (-let [class (format "spoiler-%s" color)]
                  (concat
                   ;; In HTML, a ‘style’ can be, technically, almost anywhere...
                   (format "<style> .%s {color: %s; background-color:%s;} .%s:hover {color: black; background-color:white;} </style>\n"
                           class color color class)
                   (s-replace-regexp
                    (concat (regexp-quote left) "\\(.*?\\)" (regexp-quote right))
                    (format "@@html:<span class=\"%s\"> \\1 </span>@@" class)
                    contents))))))

6. tree

﴾What You Write﴿
#+begin_box Programming ≈ Proving
#+begin_tree
+ Function Application :: f(a) : B
  - a : A
  - f : A → B

+ Modus Ponens :: q
  - p
  - p ⇒ q
#+end_tree
#+end_box
﴾What You Get﴿

Programming ≈ Proving

\[\frac{\displaystyle a : A \qquad f : A → B }{f(a) : B}[\text{Function Application}]\]\[\frac{\displaystyle p \qquad p ⇒ q}{q}[\text{Modus Ponens}]\]

﴾How It’s Implemented﴿
(org-defblock tree (&allow-other-keys :html-head (mathjax) :manual "#Aligned-equations" &context raw-contents)
              "Write a proof tree using Org-lists.

To get

         premises₀  …   premisesₙ
       ────────────────────────────[ reason ]
               conclusion

You type

       #+begin_tree
       + reason :: conclusion
         - premises₀
         - premises₁
         ⋮
         - premisesₙ
       #+end_tree

Where each premisesᵢ may, recursively, also have named reasons
and (indented) child premises of its own.

If there are multiple trees, they are shown one after the other.

The text in this block should be considered LaTeX;
as such, Org markup is not recognised.

A proof tree, derivation, is then just a deeply nested
itemisation.  For instance, assuming P = Q(X), X = Y, Q(Y) = R,
the following proves P = R.

  #+begin_tree
  + Trans :: P = R
    - P = Q(X)
      + ✓
    - Trans :: Q(X) = R
      + Trans :: Q(X) = Q(Y)
        - Refl :: Q(X) = Q(X)
          + ✓
        - Leibniz :: Q(X) = Q(Y)
          + X = Y
            - ✓
      + Sym :: Q(Y) = R
        - R = Q(Y)
          - ✓
  #+end_tree

In Markdown, each tree is a $$…$$ display, since GitHub's maths knows no \\[…\\]."
              (-let [md? (org-export-markdown-p)]
                (mapconcat (lambda (it) (format (if md? "$$%s$$" "\\[%s\\]") (org--list-to-math it)))
                           (cdr (org--parse-plain-list raw-contents "tree"))
                           (if md? "\n\n" ""))))

Generated by Emacs and Org-mode (•̀ᴗ•́)و
Creative Commons License
Life & Computing Science by Musa Al-hassy is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License