emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/org-real f80251e 116/160: Merge branch 'next' into 'mai


From: ELPA Syncer
Subject: [elpa] externals/org-real f80251e 116/160: Merge branch 'next' into 'main'
Date: Wed, 6 Oct 2021 16:58:28 -0400 (EDT)

branch: externals/org-real
commit f80251ef6b244e842a75db1034352ab039b58b91
Merge: f883078 b3d1c09
Author: Tyler Grinn <tyler@tygr.info>
Commit: Tyler Grinn <tyler@tygr.info>

    Merge branch 'next' into 'main'
    
    "in" is optional
    
    # Changed
    * `?rel=in` is optional in an org-real link\
      You can (optionally) update existing links by editing them with `C-c C-l`
    
    # Fixed
    * `org-real-include-context t` does not duplicate boxes
    * `org-real-cycle-visibility` (global) expands all sibling boxes 
automatically
    
    # New
    * Navigate by relationship with `r`
    * Color selected border and relationship box border
    * Added metadata slot and popup tooltip functionality
    
    # Improvements
    * If a headline is a link, only display description part in 
`org-real-headlines`
    * Popup buffer is resized each time a link is opened
    
    See merge request tygrdev/org-real!6
---
 README.org  |    7 +
 org-real.el | 1207 +++++++++++++++++++++++++++++++++++------------------------
 2 files changed, 723 insertions(+), 491 deletions(-)

diff --git a/README.org b/README.org
index 0f1552d..24edefc 100644
--- a/README.org
+++ b/README.org
@@ -13,6 +13,8 @@ Keep track of real things as org-mode links.
     :init
     (setq org-real-default-visibility 2
           org-real-flex-width 80
+          org-real-tooltips t
+          org-real-tooltip-timeout 0.5
           org-real-include-context t
           org-real-margin-x 2
           org-real-margin-y 1
@@ -45,6 +47,8 @@ Keep track of real things as org-mode links.
        :init
        (setq org-real-default-visibility 2
              org-real-flex-width 80
+             org-real-tooltips t
+             org-real-tooltip-timeout 0.5
              org-real-include-context t
              org-real-margin-x 2
              org-real-margin-y 1
@@ -140,6 +144,7 @@ Keep track of real things as org-mode links.
    - =RET / mouse-1= Jump to first occurrence of link
    - =o= Cycle occurrences of links in other window
    - =M-RET= Open all occurences of links by splitting the current window
+   - =r= Jump to the box directly related to the current box
 
    [[file:demo/org-real-mode.gif]]
 
@@ -176,6 +181,8 @@ Keep track of real things as org-mode links.
    [[file:demo/headline-relationships.png]]
 
 
+   The tooltip for each headline shows the values that would be
+   displayed if the org file was in org columns view.
 * Development
 
 ** Setup
diff --git a/org-real.el b/org-real.el
index b8368a3..3f13785 100644
--- a/org-real.el
+++ b/org-real.el
@@ -1,7 +1,7 @@
 ;;; org-real.el --- Keep track of real things as org-mode links -*- 
lexical-binding: t -*-
 
 ;; Author: Tyler Grinn <tylergrinn@gmail.com>
-;; Version: 0.3.2
+;; Version: 0.4.0
 ;; File: org-real.el
 ;; Package-Requires: ((emacs "26.1"))
 ;; Keywords: tools
@@ -28,6 +28,10 @@
 ;;   - to the right of
 ;;   - to the left of
 ;;
+;;   The tooltip in `org-real-headlines' shows the values for each row
+;;   in `org-columns' and can be customized the same way as org
+;;   columns view.
+;;
 ;; When in an Org Real mode diagram, the standard movement keys will
 ;; move by boxes rather than characters.  S-TAB will cycle the
 ;; visibility of all children.  Each box has the following keys:
@@ -38,6 +42,9 @@
 ;;             Pressed multiple times, cycle through occurrences.
 ;;   M-RET - Open all occurrences as separate buffers.
 ;;             This will split the current window as needed.
+;;   r     - Jump to the box directly related to the current box.
+;;             Repeated presses will eventually take you to the
+;;             top level box.
 ;;
 
 ;;; Code:
@@ -46,6 +53,7 @@
 
 (require 'eieio)
 (require 'org-element)
+(require 'org-colview)
 (require 'cl-lib)
 
 ;;;; Patch! 0.0.1 -> 0.1.0+
@@ -84,6 +92,13 @@
 (and (fboundp 'org-real--apply) (advice-remove 'org-insert-link 
#'org-real--apply))
 (and (fboundp 'org-real--maybe-edit-link) (advice-remove 'org-insert-link 
#'org-real--maybe-edit-link))
 
+;;;; Patch! 0.3.2 > 0.4.0+
+;;;; Will be removed in version 1.0.0+
+
+(and (fboundp 'org-real--jump-other-window) (fmakunbound 
'org-real--jump-other-window))
+(and (fboundp 'org-real--jump-to) (fmakunbound 'org-real--jump-to))
+(and (fboundp 'org-real--jump-all) (fmakunbound 'org-real--jump-all))
+
 ;;;; Customization variables
 
 (defgroup org-real nil
@@ -125,8 +140,27 @@
   :type 'number
   :group 'org-real)
 
+(defcustom org-real-tooltips t
+  "Show tooltips in an org real diagram."
+  :type 'boolean
+  :group 'org-real)
+
+(defcustom org-real-tooltip-timeout 0.5
+  "Idle time before showing tooltip in org real diagram."
+  :type 'number
+  :group 'org-real)
+
+(defcustom org-real-tooltip-max-width 30
+  "Maximum width of all tooltips."
+  :type 'number
+  :group 'org-real)
+
 ;;;; Faces
 
+(defface org-real-default nil
+  "Default face used in Org Real mode."
+  :group 'org-real)
+
 (defface org-real-primary nil
   "Face for the last thing in a real link."
   :group 'org-real)
@@ -136,12 +170,48 @@
  '((t :foreground "light slate blue"))
  'face-defface-spec)
 
+(defface org-real-selected nil
+  "Face for the current box under cursor."
+  :group 'org-real)
+
+(face-spec-set
+ 'org-real-selected
+ '((t :foreground "light slate blue"))
+ 'face-defface-spec)
+
+(defface org-real-rel nil
+  "Face for the box which is related to the box under the cursor."
+  :group 'org-real)
+
+(face-spec-set
+ 'org-real-rel
+ '((t :foreground "hot pink"))
+ 'face-defface-spec)
+
+(defface org-real-popup nil
+  "Face for popups in an Org Real diagram."
+  :group 'org-real)
+
+(face-spec-set
+ 'org-real-popup
+ '((((background dark)) (:background "gray30" :foreground "gray"))
+   (t (:background "gainsboro" :foreground "dim gray")))
+ 'face-defface-spec)
+
 ;;;; Constants & variables
 
 (defconst org-real-prepositions
   '("in" "on" "behind" "in front of" "above" "below" "to the left of" "to the 
right of" "on top of")
   "List of available prepositions for things.")
 
+(defconst org-real-children-prepositions
+  '("in" "on" "behind" "in front of" "on top of")
+  "List of prepositions which are rendered as children.")
+
+(defconst org-real-flex-prepositions
+  '("in" "on" "behind")
+  "List of prepositions for which boxes are flexibly added to their parent.")
+
 ;;;; Interactive functions
 
 (defun org-real-world ()
@@ -247,18 +317,23 @@ MAX-LEVEL is the maximum level to show headlines for."
 (defvar org-real--box-ring '()
   "List of buffer positions of buttons in an Org Real diagram.")
 (make-variable-buffer-local 'org-real--box-ring)
+
 (defvar org-real--current-box nil
   "Current box the buffer is displaying.")
 (make-variable-buffer-local 'org-real--current-box)
+
 (defvar org-real--current-containers '()
   "Current containers the buffer is displaying.")
 (make-variable-buffer-local 'org-real--current-containers)
+
 (defvar org-real--current-offset 0
   "Current offset for the box diagram.")
 (make-variable-buffer-local 'org-real--current-offset)
+
 (defvar org-real--visibility org-real-default-visibility
   "Visibility of children in the current org real diagram.")
 (make-variable-buffer-local 'org-real--visibility)
+
 (defvar org-real--max-visibility 3
   "Maximum visibility setting allowed when cycling all children.")
 (make-variable-buffer-local 'org-real--max-visibility)
@@ -281,7 +356,7 @@ MAX-LEVEL is the maximum level to show headlines for."
   (let ((col (current-column)))
     (forward-line 1)
     (org-real-mode-cycle)
-    (move-to-column col t)
+    (move-to-column col)
     (let ((pos (point)))
       (goto-char (seq-reduce
                   (lambda (closest p)
@@ -298,7 +373,7 @@ MAX-LEVEL is the maximum level to show headlines for."
   (let ((col (current-column)))
     (forward-line -1)
     (org-real-mode-uncycle)
-    (move-to-column col t)
+    (move-to-column col)
     (let ((pos (point)))
       (goto-char (seq-reduce
                   (lambda (closest p)
@@ -329,26 +404,22 @@ MAX-LEVEL is the maximum level to show headlines for."
   (org-real--flex-adjust org-real--current-box)
   (let ((inhibit-read-only t))
     (erase-buffer)
-    (setq org-real--box-ring '())
     (if org-real--current-containers
         (org-real--pp-text org-real--current-containers))
     (setq org-real--current-offset (- (line-number-at-pos)
                                       org-real-margin-y
                                       (* 2 org-real-padding-y)))
-    (let ((box-coords (org-real--draw org-real--current-box)))
-      (setq org-real--box-ring
-            (seq-sort
-             '<
-             (mapcar
-              (lambda (coords)
-                (forward-line (- (car coords) (line-number-at-pos)))
-                (move-to-column (cdr coords))
-                (point))
-              box-coords))))
+    (org-real--draw org-real--current-box)
+    (org-real-mode-recalculate-box-ring)
     (goto-char (point-max))
     (insert "\n")
     (goto-char 0)))
 
+(defun org-real-mode-recalculate-box-ring ()
+  "Recalculate the position of all boxes in `org-real--current-box'."
+  (setq org-real--box-ring
+        (seq-sort '< (org-real--get-positions org-real--current-box))))
+
 (define-derived-mode org-real-mode special-mode
   "Org Real"
   "Mode for viewing an org-real diagram.
@@ -357,8 +428,10 @@ The following commands are available:
 
 \\{org-real-mode-map}"
   :group 'org-mode
-  (setq indent-tabs-mode nil)
-  (let ((inhibit-message t)) (toggle-truncate-lines t)))
+  (let ((inhibit-message t))
+    (setq indent-tabs-mode nil)
+    (cursor-sensor-mode t)
+    (toggle-truncate-lines t)))
 
 (mapc
  (lambda (key) (define-key org-real-mode-map (kbd (car key)) (cdr key)))
@@ -402,6 +475,8 @@ it.
 VISIBILITY is the initial visibility of children and
 MAX-VISIBILITY is the maximum depth to display when cycling
 visibility."
+  (if-let ((buffer (get-buffer "Org Real")))
+      (kill-buffer buffer))
   (let ((buffer (get-buffer-create "Org Real")))
     (with-current-buffer buffer
       (org-real-mode)
@@ -413,7 +488,6 @@ visibility."
       (org-real-mode-redraw)
       (let* ((width (apply 'max (mapcar 'length (split-string (buffer-string) 
"\n"))))
              (height (count-lines (point-min) (point-max)))
-             (buffer (get-buffer-create "Org Real"))
              (window (or (get-buffer-window buffer)
                          (display-buffer buffer
                                          `(,(or display-buffer-fn
@@ -456,19 +530,22 @@ visibility."
          (box (org-real--make-instance 'org-real-box (copy-tree containers))))
     (if org-real-include-context
         (let* ((primary-name (plist-get (car (reverse containers)) :name))
-               (children (mapcar
-                          (lambda (containers)
-                            (org-real--make-instance 'org-real-box containers 
t))
-                          (seq-filter
-                           (lambda (containers)
-                             (let ((rel-containers (reverse containers)))
-                               (pop rel-containers) ;; Exclude copies of the 
same thing
-                               (seq-some
-                                (lambda (rel-container)
-                                  (string= primary-name (plist-get 
rel-container :name)))
-                                rel-containers)))
-                           (org-real--parse-buffer)))))
-          (setq box (org-real--merge (push box children)))))
+               (container-matrix (seq-filter
+                                  (lambda (containers)
+                                    (let ((rel-containers (reverse 
containers)))
+                                      (pop rel-containers) ;; Exclude copies 
of the same thing
+                                      (seq-some
+                                       (lambda (rel-container)
+                                         (string= primary-name (plist-get 
rel-container :name)))
+                                       rel-containers)))
+                                  (org-real--parse-buffer)))
+               (context-boxes (mapcar
+                               (lambda (containers)
+                                 (org-real--make-instance 'org-real-box 
containers t))
+                               container-matrix)))
+          (mapc
+           (lambda (context) (org-real--merge-into context box))
+           context-boxes)))
     (org-real--pp box (copy-tree containers) nil nil 0)))
 
 (defun org-real-complete (&optional existing)
@@ -562,7 +639,7 @@ ORIG is `org-insert-link', ARGS are the arguments passed to 
it."
                                                           (ignore-errors
                                                             (url-type
                                                              
(url-generic-parse-url link))))
-                                                 (plist-get (car (last 
(org-real--parse-url link nil)))
+                                                 (plist-get (car (last 
(org-real--parse-url link)))
                                                             :name))))))
     (unwind-protect
         (if (called-interactively-p 'any)
@@ -587,6 +664,14 @@ ORIG is `org-insert-link', ARGS are the arguments passed 
to it."
          :type string)
    (rel :initarg :rel
         :type string)
+   (primary :initarg :primary
+            :initform nil
+            :type boolean)
+   (locations :initarg :locations
+              :initform '()
+              :type list)
+   (metadata :initarg :metadata
+             :type string)
    (rel-box :initarg :rel-box
             :type org-real-box)
    (x-order :initarg :x-order
@@ -630,16 +715,9 @@ ORIG is `org-insert-link', ARGS are the arguments passed 
to it."
            :type number)
    (flex :initarg :flex
          :initform nil
-         :type boolean)
-   (primary :initarg :primary
-            :initform nil
-            :type boolean)
-   (locations :initarg :locations
-              :initform '()
-              :type list))
+         :type boolean))
   "A representation of a box in 3D space.")
 
-
 (cl-defmethod org-real--get-all ((collection org-real-box-collection))
   "Get all boxes in COLLECTION as a sequence."
   (with-slots (box next) collection
@@ -688,39 +766,78 @@ non-nil, skip setting :primary slot on the last box."
         (org-real--merge-into (pop boxes) world))
       world)))
 
+(cl-defmethod org-real--merge-into ((from org-real-box) (to org-real-box))
+  "Merge FROM box into TO box."
+  (let (match-found)
+    (mapc
+     (lambda (from-box)
+       (let ((match (org-real--find-matching from-box to)))
+         (while (and (not match) (slot-boundp from-box :rel-box))
+           (setq from-box (with-slots (rel-box) from-box rel-box))
+           (setq match (org-real--find-matching from-box to)))
+         (when match
+           (setq match-found t)
+           (org-real--add-matching from-box match))))
+     (org-real--primary-boxes from))
+    (unless match-found
+      (let ((all-from-children (org-real--get-children from 'all)))
+        (with-slots ((to-children children) (to-behind behind)) to
+          (if (= 1 (length all-from-children))
+              (org-real--flex-add (car all-from-children) to)
+            (org-real--flex-add from to)))))))
+
 (cl-defmethod org-real--update-visibility ((box org-real-box))
   "Update visibility of BOX and all of its children."
   (with-slots (level children hidden-children expand-children) box
-    (if (or (= 0 org-real--visibility)
-            (<= level org-real--visibility))
-        (progn
-          (when (slot-boundp box :expand-children)
-            (funcall expand-children box)
-            (slot-makeunbound box :expand-children))
-          (if (org-real--get-all hidden-children)
-              (cl-rotatef children hidden-children))
+    (if (not (org-real--is-visible box))
+        (if (not (org-real--get-all hidden-children)) (cl-rotatef children 
hidden-children))
+      (when (slot-boundp box :expand-children)
+        (funcall expand-children box)
+        (slot-makeunbound box :expand-children))
+      (if (org-real--get-all hidden-children)
+          (cl-rotatef children hidden-children))
+      (let (fully-expanded)
+        (while (not fully-expanded)
+          (setq fully-expanded t)
           (mapc
            (lambda (child)
              (with-slots (expand-siblings) child
                (when (slot-boundp child :expand-siblings)
                  (funcall expand-siblings child)
-                 (slot-makeunbound child :expand-siblings))))
-           (org-real--get-all children)))
-      (if (not (org-real--get-all hidden-children)) (cl-rotatef children 
hidden-children)))
-    (mapc 'org-real--update-visibility (append (org-real--get-all children)
-                                               (org-real--get-all 
hidden-children)))))
+                 (slot-makeunbound child :expand-siblings)
+                 (setq fully-expanded nil))))
+           (org-real--get-all children))))))
+  (mapc 'org-real--update-visibility (org-real--get-children box 'all)))
+
+(cl-defmethod org-real--get-positions ((box org-real-box))
+  "Get the buffer position of the names of BOX and its children."
+  (if-let ((pos (and (slot-boundp box :name)
+                     (let ((top (org-real--get-top box))
+                           (left (org-real--get-left box)))
+                       (forward-line (- (+ org-real--current-offset 1 top 
org-real-padding-y)
+                                        (line-number-at-pos)))
+                       (move-to-column (+ 1 left org-real-padding-x))
+                       (point)))))
+      (apply 'append (list pos) (mapcar 'org-real--get-positions 
(org-real--get-children box)))
+    (apply 'append (mapcar 'org-real--get-positions (org-real--get-children 
box)))))
+
 
 ;;;; Drawing
 
-(cl-defmethod org-real--draw ((box org-real-box))
+(cl-defmethod org-real--draw ((box org-real-box) &optional arg)
   "Insert an ascii drawing of BOX into the current buffer.
 
-OFFSET is the starting line to start insertion.
+If ARG is non-nil, skip drawing children boxes and only update
+text properties on the border.  If ARG is 'selected, draw the
+border using the `org-real-selected' face.  If ARG is 'rel, draw
+the border using `org-real-rel' face, else use `org-real-default'
+face.
+
+Uses `org-real--current-offset' to determine row offset.
 
 Adds to list `org-real--box-ring' the buffer position of each
 button drawn."
-  (let ((children (with-slots (children) box (org-real--get-all children)))
-        box-coords)
+  (let (box-coords)
     (with-slots
         (name
          behind
@@ -744,29 +861,44 @@ button drawn."
                            (when (< (line-number-at-pos) (car coords))
                              (insert (make-string (- (car coords) 
(line-number-at-pos)) ?\n)))
                            (move-to-column (cdr coords) t)
-                           (if primary (put-text-property 0 (length str)
-                                                          'face 
'org-real-primary str))
-                           (insert str)
-                           (let ((remaining-chars (- (save-excursion 
(end-of-line) (current-column))
-                                                     (current-column))))
-                             (delete-char (min (length str) remaining-chars))))
+                           (if arg
+                               (ignore-errors
+                                 (put-text-property (point) (+ (length str) 
(point))
+                                                    'face (cond ((eq arg 
'selected) 'org-real-selected)
+                                                                ((eq arg 'rel) 
'org-real-rel)
+                                                                (t 
'org-real-default))))
+                             (put-text-property 0 (length str)
+                                                'face (if primary
+                                                          'org-real-primary
+                                                        'org-real-default)
+                                                str)
+                             (insert str)
+                             (let ((remaining-chars (- (save-excursion 
(end-of-line) (current-column))
+                                                       (current-column))))
+                               (delete-char (min (length str) 
remaining-chars)))))
                      (draw-name (coords str &optional primary)
-                                (if (not locations)
-                                    (draw coords str primary)
-                                  (forward-line (- (car coords) 
(line-number-at-pos)))
-                                  (when (< (line-number-at-pos) (car coords))
-                                    (insert (make-string (- (car coords) 
(line-number-at-pos)) ?\n)))
-                                  (move-to-column (cdr coords) t)
-                                  (setq box-coords coords)
-                                  (if primary (put-text-property 0 (length str)
-                                                                 'face 
'org-real-primary str))
-                                  (insert-button str
-                                                 'help-echo "Jump to first 
occurence"
-                                                 'keymap 
(org-real--create-button-keymap box))
-                                  (let ((remaining-chars (- (save-excursion 
(end-of-line)
-                                                                            
(current-column))
+                                (when (not arg)
+                                  (if (not locations)
+                                      (draw coords str primary)
+                                    (forward-line (- (car coords) 
(line-number-at-pos)))
+                                    (when (< (line-number-at-pos) (car coords))
+                                      (insert (make-string (- (car coords) 
(line-number-at-pos)) ?\n)))
+                                    (move-to-column (cdr coords) t)
+                                    (setq box-coords coords)
+                                    (if primary (put-text-property 0 (length 
str)
+                                                                   'face 
'org-real-primary
+                                                                   str))
+                                    (put-text-property 0 (length str)
+                                                       'cursor-sensor-functions
+                                                       (list 
(org-real--create-cursor-function box))
+                                                       str)
+                                    (insert-button str
+                                                   'help-echo "Jump to first 
occurence"
+                                                   'keymap 
(org-real--create-button-keymap box))
+                                    (let ((remaining-chars (- (save-excursion 
(end-of-line)
+                                                                              
(current-column))
                                                             (current-column))))
-                                    (delete-char (min (length str) 
remaining-chars))))))
+                                      (delete-char (min (length str) 
remaining-chars)))))))
             (draw (cons top left)
                   (concat (if double "╔" "┌")
                           (make-string (- width 2) (cond (dashed #x254c)
@@ -800,9 +932,13 @@ button drawn."
                                         (double "║")
                                         (t "│")))
                 (setq r (+ r 1))))))))
-    (apply 'append
-           (if box-coords (list box-coords) nil)
-           (mapcar 'org-real--draw children))))
+    (if arg
+        (if box-coords (list box-coords) nil)
+      (apply 'append
+             (if box-coords (list box-coords) nil)
+             (mapcar
+              'org-real--draw
+              (org-real--get-children box))))))
 
 (cl-defmethod org-real--get-width ((box org-real-box))
   "Get the width of BOX."
@@ -815,7 +951,7 @@ button drawn."
                        (if (slot-boundp box :name)
                            (with-slots (name) box (length name))
                          0)))
-             (children (with-slots (children) box (org-real--get-all 
children))))
+             (children (org-real--get-children box)))
         (if (not children)
             (setq stored-width width)
           (let* ((row-indices (cl-delete-duplicates
@@ -855,11 +991,11 @@ button drawn."
           (seq-filter
            (lambda (child) (with-slots (rel) child (and (slot-boundp child 
:rel)
                                                         (string= rel "on top 
of"))))
-           (with-slots (children) box (org-real--get-all children))))))
+           (org-real--get-children box)))))
 
 (cl-defmethod org-real--get-on-top-height-helper ((child org-real-box))
   "Get the height of any boxes on top of CHILD, including child."
-  (with-slots (children rel) child
+  (with-slots (rel) child
     (+
      (org-real--get-height child)
      (apply 'max 0
@@ -870,7 +1006,7 @@ button drawn."
                 (with-slots ((grandchild-rel rel)) grandchild
                   (and (slot-boundp grandchild :rel)
                        (string= "on top of" grandchild-rel))))
-              (org-real--get-all children)))))))
+              (org-real--get-children child)))))))
 
 (cl-defmethod org-real--get-height ((box org-real-box) &optional 
include-on-top)
   "Get the height of BOX.
@@ -885,7 +1021,7 @@ If INCLUDE-ON-TOP is non-nil, also include height on top 
of box."
                          (* 2 org-real-padding-y)))
               (children (seq-filter
                          (lambda (child) (with-slots (on-top) child (not 
on-top)))
-                         (with-slots (children) box (org-real--get-all 
children)))))
+                         (org-real--get-children box))))
           (if (not children)
               (progn
                 (setq stored-height height)
@@ -921,12 +1057,11 @@ If INCLUDE-ON-TOP is non-nil, also include height on top 
of box."
            (let ((on-top-height (org-real--get-on-top-height box)))
              (if (not (slot-boundp box :parent))
                  (setq stored-top on-top-height)
-               (let* ((siblings (with-slots (children) parent
-                                  (seq-filter
-                                   (lambda (sibling)
-                                     (with-slots (on-top in-front) sibling
-                                       (not (or on-top in-front))))
-                                   (org-real--get-all children))))
+               (let* ((siblings (seq-filter
+                                 (lambda (sibling)
+                                   (with-slots (on-top in-front) sibling
+                                     (not (or on-top in-front))))
+                                 (org-real--get-children parent)))
                       (offset (+ 2 org-real-padding-y org-real-margin-y))
                       (top (+ on-top-height offset (org-real--get-top 
parent))))
                  (if-let* ((directly-above (seq-reduce
@@ -956,44 +1091,233 @@ If INCLUDE-ON-TOP is non-nil, also include height on 
top of box."
 
 (cl-defmethod org-real--get-left ((box org-real-box))
   "Get the left column index of BOX."
-  (with-slots ((stored-left left)) box
+  (with-slots ((stored-left left) parent x-order y-order) box
     (if (slot-boundp box :left)
         stored-left
       (if (not (slot-boundp box :parent))
           (setq stored-left 0)
-        (with-slots (parent x-order y-order) box
-          (let* ((left (+ 1
-                          org-real-padding-x
-                          (org-real--get-left parent)))
-                 (to-the-left (seq-filter
-                               (lambda (child)
-                                 (with-slots ((child-y y-order) (child-x 
x-order)) child
-                                   (and (= y-order child-y)
-                                        (< child-x x-order))))
-                               (org-real--get-all (with-slots (children) 
parent children))))
-                 (directly-left (and to-the-left
-                                     (seq-reduce
-                                      (lambda (max child)
-                                        (with-slots ((max-x x-order)) max
-                                          (with-slots ((child-x x-order)) child
-                                            (if (> child-x max-x)
-                                                child
-                                              max))))
-                                      to-the-left
-                                      (org-real-box :x-order -1.0e+INF)))))
-            (if directly-left
-                (setq stored-left (+ (org-real--get-left directly-left)
-                                     (org-real--get-width directly-left)
-                                     org-real-margin-x))
-              (with-slots (rel rel-box) box
-                (if (and (slot-boundp box :rel)
-                         (or (string= "above" rel)
+        (let* ((left (+ 1
+                        org-real-padding-x
+                        (org-real--get-left parent)))
+               (to-the-left (seq-filter
+                             (lambda (child)
+                               (with-slots ((child-y y-order) (child-x 
x-order)) child
+                                 (and (= y-order child-y)
+                                      (< child-x x-order))))
+                             (org-real--get-children parent)))
+               (directly-left (and to-the-left
+                                   (seq-reduce
+                                    (lambda (max child)
+                                      (with-slots ((max-x x-order)) max
+                                        (with-slots ((child-x x-order)) child
+                                          (if (> child-x max-x)
+                                              child
+                                            max))))
+                                    to-the-left
+                                    (org-real-box :x-order -1.0e+INF)))))
+          (if directly-left
+              (setq stored-left (+ (org-real--get-left directly-left)
+                                   (org-real--get-width directly-left)
+                                   org-real-margin-x))
+            (with-slots (rel rel-box) box
+              (if (and (slot-boundp box :rel)
+                       (or (string= "above" rel)
                              (string= "below" rel)))
-                    (setq stored-left (org-real--get-left rel-box))
-                  (setq stored-left left))))))))))
+                  (setq stored-left (org-real--get-left rel-box))
+                (setq stored-left left)))))))))
+
+;;;; Org real mode buttons
+
+(cl-defmethod org-real--create-cursor-function ((box org-real-box))
+  "Create cursor functions for entering and leaving BOX."
+  (with-slots (rel rel-box name metadata) box
+    (let (tooltip-timer)
+      (lambda (_window _oldpos dir)
+        (let ((inhibit-read-only t))
+          (save-excursion
+            (if (eq dir 'entered)
+                (progn
+                  (if (slot-boundp box :metadata)
+                      (setq tooltip-timer (org-real--tooltip metadata))
+                    (if (and (slot-boundp box :name) (slot-boundp box :rel))
+                        (with-slots ((rel-name name)) rel-box
+                          (setq tooltip-timer
+                                (org-real--tooltip
+                                 (with-temp-buffer
+                                   (insert (format "The %s is %s the %s."
+                                                   name rel rel-name))
+                                   (let ((fill-column 
org-real-tooltip-max-width))
+                                     (fill-paragraph t))
+                                   (buffer-string)))))))
+                  (if (slot-boundp box :rel-box)
+                      (org-real--draw rel-box 'rel))
+                  (org-real--draw box 'selected))
+              (if tooltip-timer (cancel-timer tooltip-timer))
+              (if (slot-boundp box :rel-box)
+                  (org-real--draw rel-box t))
+              (org-real--draw box t))))))))
+
+(cl-defmethod org-real--jump-other-window ((box org-real-box))
+  "Jump to location of link for BOX in other window."
+  (with-slots (locations) box
+    (lambda ()
+      (interactive)
+      (let ((first (car locations)))
+        (object-remove-from-list box :locations first)
+        (object-add-to-list box :locations first t))
+      (let* ((marker (car locations))
+             (buffer (marker-buffer marker))
+             (pos (marker-position marker)))
+        (save-selected-window
+          (switch-to-buffer-other-window buffer)
+          (goto-char pos))))))
+
+(cl-defmethod org-real--jump-to ((box org-real-box))
+  "Jump to the first occurrence of a link for BOX in the same window."
+  (with-slots (locations) box
+    (lambda ()
+      (interactive)
+      (let* ((marker (car locations))
+             (buffer (marker-buffer marker))
+             (pos (marker-position marker)))
+        (if-let ((window (get-buffer-window buffer)))
+            (select-window window)
+          (switch-to-buffer buffer))
+        (goto-char pos)))))
+
+(cl-defmethod org-real--jump-all ((box org-real-box))
+  "View all occurrences of links from BOX in the same window."
+  (with-slots (locations) box
+    (lambda ()
+      (interactive)
+      (let* ((size (/ (window-height) (length locations)))
+             (marker (car locations)))
+        (or (<= window-min-height size)
+            (error "To many buffers to visit simultaneously"))
+        (switch-to-buffer (marker-buffer marker))
+        (goto-char (marker-position marker))
+        (dolist (marker (cdr locations))
+          (select-window (split-window nil size))
+          (switch-to-buffer (marker-buffer marker))
+          (goto-char (marker-position marker)))))))
+
+(cl-defmethod org-real--jump-rel ((box org-real-box))
+  "Jump to the box directly related to BOX."
+  (with-slots (rel-box) box
+    (if (not (slot-boundp box :rel-box))
+        (lambda () (interactive))
+      (let ((left (org-real--get-left rel-box))
+            (top (org-real--get-top rel-box)))
+        (lambda ()
+          (interactive)
+          (forward-line (- (+ org-real--current-offset top 1 
org-real-padding-y)
+                           (line-number-at-pos)))
+          (move-to-column (+ left 1 org-real-padding-x)))))))
+
+(cl-defmethod org-real--create-button-keymap ((box org-real-box))
+  "Create a keymap for a button in Org Real mode.
+
+BOX is the box the button is being made for."
+  (with-slots (locations) box
+    (easy-mmode-define-keymap
+     (mapcar
+      (lambda (key) (cons (kbd (car key)) (cdr key)))
+      `(("TAB"       . ,(org-real--cycle-children box))
+        ("o"         . ,(org-real--jump-other-window box))
+        ("r"         . ,(org-real--jump-rel box))
+        ("<mouse-1>" . ,(org-real--jump-to box))
+        ("RET"       . ,(org-real--jump-to box))
+        ("M-RET"     . ,(org-real--jump-all box)))))))
 
 ;;;; Private class methods
 
+(cl-defmethod org-real--is-visible ((box org-real-box))
+  "Determine if BOX is visible according to `org-real--visibility'."
+  (with-slots (level) box
+    (or (= 0 org-real--visibility)
+        (<= level org-real--visibility))))
+
+(cl-defmethod org-real--get-children ((box org-real-box) &optional arg)
+  "Get all visible children of BOX.
+
+If optional ARG is 'all, include hidden children.
+
+If optional ARG is 'hidden, only return hidden children"
+  (with-slots (children hidden-children) box
+    (cond
+     ((eq 'all arg)
+      (append (org-real--get-all children)
+              (org-real--get-all hidden-children)))
+     ((eq 'hidden arg)
+      (org-real--get-all hidden-children))
+     (t
+      (org-real--get-all children)))))
+
+(cl-defmethod org-real--add-child ((parent org-real-box)
+                                   (child org-real-box)
+                                   &optional force-visible)
+  "Add CHILD to PARENT according to its visibility.
+
+If FORCE-VISIBLE, always make CHILD visible in PARENT."
+  (oset child :parent parent)
+  (with-slots (children hidden-children) parent
+    (if (or force-visible (org-real--is-visible child))
+        (setq children (org-real--push children child))
+      (setq hidden-children (org-real--push hidden-children child)))))
+
+(cl-defmethod org-real--get-world ((box org-real-box))
+  "Get the top most box related to BOX."
+  (with-slots (parent) box
+    (if (slot-boundp box :parent)
+        (org-real--get-world parent)
+      box)))
+
+(cl-defmethod org-real--primary-boxes ((box org-real-box))
+  "Get a list of boxes from BOX which have no further relatives."
+  (if (slot-boundp box :parent)
+      (if-let ((next-boxes (org-real--next box)))
+          (apply 'append (mapcar 'org-real--primary-boxes next-boxes))
+        (list box))
+    (apply 'append (mapcar 'org-real--primary-boxes (org-real--get-children 
box 'all)))))
+
+(cl-defmethod org-real--expand ((box org-real-box))
+  "Get a list of all boxes, including BOX, that are children of BOX."
+  (if (slot-boundp box :parent)
+      (apply 'append (list box) (mapcar 'org-real--expand (org-real--next 
box)))
+    (apply 'append (mapcar 'org-real--expand (org-real--get-children box 
'all)))))
+
+(cl-defmethod org-real--make-dirty ((box org-real-box))
+  "Clear all TOP LEFT WIDTH and HEIGHT coordinates from BOX and its children."
+  (if (slot-boundp box :top) (slot-makeunbound box :top))
+  (if (slot-boundp box :left) (slot-makeunbound box :left))
+  (if (slot-boundp box :width) (slot-makeunbound box :width))
+  (if (slot-boundp box :height) (slot-makeunbound box :height))
+  (mapc 'org-real--make-dirty (org-real--get-children box 'all)))
+
+;; TODO check if `eq' works
+(cl-defmethod org-real--next ((box org-real-box) &optional exclude-children)
+  "Retrieve any boxes for which the :rel-box slot is BOX.
+
+If EXCLUDE-CHILDREN, only retrieve sibling boxes."
+  (let ((relatives (append (if exclude-children '() (org-real--get-children 
box 'all))
+                           (if (slot-boundp box :parent)
+                               (with-slots (parent) box
+                                 (org-real--get-children parent 'all))
+                             '()))))
+    (seq-filter
+     (lambda (relative)
+       (with-slots (rel-box) relative
+         (and (slot-boundp relative :rel-box)
+              (eq rel-box box))))
+     relatives)))
+
+(cl-defmethod org-real--apply-level ((box org-real-box) level)
+  "Apply LEVEL to BOX and update all of its children."
+  (oset box :level level)
+  (mapc
+   (lambda (child) (org-real--apply-level child (+ 1 level)))
+   (org-real--get-children box 'all)))
+
 (cl-defmethod org-real--make-instance-helper (containers
                                               (parent org-real-box)
                                               (prev org-real-box)
@@ -1022,156 +1346,86 @@ PREV must already exist in PARENT."
              (prev-on-top on-top)
              (prev-in-front in-front))
             prev
-          (with-slots ((siblings children) (hidden-siblings hidden-children)) 
parent
+          (cond
+           ((or (string= rel "in") (string= rel "on"))
+            (setq cur-level (+ 1 prev-level))
+            (setq cur-behind prev-behind))
+           ((string= rel "behind")
+            (setq cur-level (+ 1 prev-level))
+            (setq cur-behind t))
+           ((string= rel "in front of")
+            (setq cur-level (+ 1 prev-level))
+            (setq cur-y 1.0e+INF)
+            (setq cur-behind prev-behind)
+            (setq cur-in-front t))
+           ((string= rel "on top of")
+            (setq cur-level (+ 1 prev-level))
+            (setq cur-y -1.0e+INF)
+            (setq cur-behind prev-behind)
+            (setq cur-on-top t))
+           ((member rel '("above" "below"))
+            (setq cur-behind prev-behind)
+            (setq cur-x prev-x)
             (cond
-             ((or (string= rel "in") (string= rel "on"))
-              (setq cur-level (+ 1 prev-level))
-              (setq cur-behind prev-behind))
-             ((string= rel "behind")
-              (setq cur-level (+ 1 prev-level))
-              (setq cur-behind t))
-             ((string= rel "in front of")
-              (setq cur-level (+ 1 prev-level))
-              (setq cur-y 1.0e+INF)
-              (setq cur-behind prev-behind)
-              (setq cur-in-front t))
-             ((string= rel "on top of")
-              (setq cur-level (+ 1 prev-level))
-              (setq cur-y -1.0e+INF)
-              (setq cur-behind prev-behind)
-              (setq cur-on-top t))
-             ((member rel '("above" "below"))
-              (setq cur-behind prev-behind)
-              (setq cur-x prev-x)
-              (cond
-               ((and prev-in-front (string= rel "below"))
-                (while (with-slots (in-front) prev in-front)
-                  (setq prev (with-slots (parent) prev parent)))
-                (setq parent (with-slots (parent) prev parent)))
-               ((and prev-on-top (string= rel "above"))
-                (while (with-slots (on-top) prev on-top)
-                  (setq prev (with-slots (parent) prev parent)))
-                (setq parent (with-slots (parent) prev parent)))
-               ((and prev-on-top (string= rel "below"))
-                (setq rel "in")
-                (setq prev parent)))
-              (setq cur-level (+ 1 (with-slots (level) parent level)))
-              (let ((sibling-y-orders
-                     (with-slots ((siblings children) (hidden-siblings 
hidden-children)) parent
-                       (mapcar
-                        (lambda (sibling) (with-slots (y-order) sibling 
y-order))
-                        (seq-filter
-                         (lambda (sibling)
-                           (with-slots (in-front on-top) sibling
-                             (not (or in-front on-top))))
-                         (append (org-real--get-all siblings)
-                                 (org-real--get-all hidden-siblings)))))))
-                (if (or prev-on-top (string= rel "above"))
-                    (setq cur-y (- (apply 'min 0 sibling-y-orders) 1))
-                  (setq cur-y (+ 1 (apply 'max 0 sibling-y-orders))))))
-             ((member rel '("to the left of" "to the right of"))
-              (setq cur-level prev-level)
-              (setq cur-y prev-y)
-              (setq cur-behind prev-behind)
-              (setq cur-on-top prev-on-top)
-              (setq cur-in-front prev-in-front)
-              (if (string= rel "to the left of")
-                  (setq cur-x prev-x)
-                (setq cur-x (+ 1 prev-x)))
-              (let ((row-siblings (seq-filter
-                                   (lambda (sibling)
-                                     (with-slots (y-order) sibling
-                                       (= prev-y y-order)))
-                                   (append (org-real--get-all siblings)
-                                           (org-real--get-all 
hidden-siblings)))))
-                (mapc
-                 (lambda (sibling)
-                   (with-slots (x-order) sibling
-                     (if (>= x-order cur-x)
-                         (setq x-order (+ 1 x-order)))))
-                 row-siblings))))
-            (oset box :rel rel)
-            (oset box :rel-box prev)
-            (if (not (slot-boundp box :name)) (setq cur-level 0))
-            (let ((visible (or (= 0 org-real--visibility) (<= cur-level 
org-real--visibility))))
-              (if (and prev (member rel '("in" "on" "behind" "in front of" "on 
top of")))
-                  (progn
-                    (oset box :parent prev)
-                    (if visible
-                        (with-slots (children) prev
-                          (setq children (org-real--push children box)))
-                      (with-slots (hidden-children) prev
-                        (setq hidden-children (org-real--push hidden-children 
box))))
-                    (if containers
-                        (org-real--make-instance-helper containers prev box 
skip-primary)
-                      (unless skip-primary (oset box :primary t))))
-                (oset box :parent parent)
-                (if visible
-                    (with-slots (children) parent
-                      (setq children (org-real--push children box)))
-                  (with-slots (hidden-children) parent
-                    (setq hidden-children (org-real--push hidden-children 
box))))
+             ((and prev-in-front (string= rel "below"))
+              (while (with-slots (in-front) prev in-front)
+                (setq prev (with-slots (parent) prev parent)))
+              (setq parent (with-slots (parent) prev parent)))
+             ((and prev-on-top (string= rel "above"))
+              (while (with-slots (on-top) prev on-top)
+                (setq prev (with-slots (parent) prev parent)))
+              (setq parent (with-slots (parent) prev parent)))
+             ((and prev-on-top (string= rel "below"))
+              (setq rel "in")
+              (setq prev parent)))
+            (setq cur-level (+ 1 (with-slots (level) parent level)))
+            (let ((sibling-y-orders
+                   (mapcar
+                    (lambda (sibling) (with-slots (y-order) sibling y-order))
+                    (seq-filter
+                     (lambda (sibling)
+                       (with-slots (in-front on-top) sibling
+                         (not (or in-front on-top))))
+                     (org-real--get-children parent 'all)))))
+              (if (or prev-on-top (string= rel "above"))
+                  (setq cur-y (- (apply 'min 0 sibling-y-orders) 1))
+                (setq cur-y (+ 1 (apply 'max 0 sibling-y-orders))))))
+           ((member rel '("to the left of" "to the right of"))
+            (setq cur-level prev-level)
+            (setq cur-y prev-y)
+            (setq cur-behind prev-behind)
+            (setq cur-on-top prev-on-top)
+            (setq cur-in-front prev-in-front)
+            (if (string= rel "to the left of")
+                (setq cur-x prev-x)
+              (setq cur-x (+ 1 prev-x)))
+            (let ((row-siblings (seq-filter
+                                 (lambda (sibling)
+                                   (with-slots (y-order) sibling
+                                     (= prev-y y-order)))
+                                 (org-real--get-children parent 'all))))
+              (mapc
+               (lambda (sibling)
+                 (with-slots (x-order) sibling
+                   (if (>= x-order cur-x)
+                       (setq x-order (+ 1 x-order)))))
+               row-siblings))))
+          (oset box :rel rel)
+          (oset box :rel-box prev)
+          (if (not (slot-boundp box :name)) (setq cur-level 0))
+          (if (member rel org-real-children-prepositions)
+              (progn
+                (org-real--add-child prev box)
                 (if containers
-                    (org-real--make-instance-helper containers parent box 
skip-primary)
-                  (unless skip-primary (oset box :primary t))))))))))
-
-(cl-defmethod org-real--get-world ((box org-real-box))
-  "Get the top most box related to BOX."
-  (with-slots (parent) box
-    (if (slot-boundp box :parent)
-        (org-real--get-world parent)
-      box)))
-
-(cl-defmethod org-real--make-dirty (box)
-  "Clear all TOP LEFT WIDTH and HEIGHT coordinates from BOX and its children."
-  (if (slot-boundp box :top) (slot-makeunbound box :top))
-  (if (slot-boundp box :left) (slot-makeunbound box :left))
-  (if (slot-boundp box :width) (slot-makeunbound box :width))
-  (if (slot-boundp box :height) (slot-makeunbound box :height))
-  (with-slots (children hidden-children) box
-    (mapc 'org-real--make-dirty (append (org-real--get-all children)
-                                        (org-real--get-all hidden-children)))))
-
-(cl-defmethod org-real--next ((box org-real-box) &optional exclude-children)
-  "Retrieve any boxes for which the :rel-box slot is BOX.
-
-If EXCLUDE-CHILDREN, only retrieve sibling boxes."
-  (let ((relatives (append (if exclude-children '() (with-slots (children 
hidden-children) box
-                                                      (append 
(org-real--get-all children)
-                                                              
(org-real--get-all hidden-children))))
-                           (if (slot-boundp box :parent)
-                                (with-slots
-                                    (children hidden-children)
-                                    (with-slots (parent) box parent)
-                                  (append (org-real--get-all children)
-                                          (org-real--get-all hidden-children)))
-                             '()))))
-    (seq-filter
-     (lambda (relative)
-       (with-slots (rel-box) relative
-         (and (slot-boundp relative :rel-box)
-              (string= (with-slots (name) rel-box name)
-                       (with-slots (name) box name)))))
-     relatives)))
-
-(cl-defmethod org-real--expand ((box org-real-box))
-  "Get a list of all boxes, including BOX, that are children of BOX."
-  (if (slot-boundp box :name)
-      (apply 'append (list box) (mapcar 'org-real--expand (org-real--next 
box)))
-    (with-slots (children) box
-      (apply 'append (mapcar 'org-real--expand (org-real--get-all 
children))))))
-
-(cl-defmethod org-real--primary-boxes ((box org-real-box))
-  "Get a list of boxes from BOX which have no further relatives."
-  (if (slot-boundp box :name)
-      (if-let ((next-boxes (org-real--next box)))
-          (apply 'append (mapcar 'org-real--primary-boxes next-boxes))
-        (list box))
-    (with-slots (children) box
-      (apply 'append (mapcar 'org-real--primary-boxes (org-real--get-all 
children))))))
+                    (org-real--make-instance-helper containers prev box 
skip-primary)
+                  (unless skip-primary (oset box :primary t))))
+            (org-real--add-child parent box)
+            (if containers
+                (org-real--make-instance-helper containers parent box 
skip-primary)
+              (unless skip-primary (oset box :primary t))))))))
 
 (cl-defmethod org-real--find-matching ((search-box org-real-box) (world 
org-real-box))
-  "Find and add box to WORLD with a matching name as SEARCH-BOX."
+  "Find a box in WORLD with a matching name as SEARCH-BOX."
   (when (slot-boundp search-box :name)
     (with-slots ((search-name name)) search-box
       (seq-find
@@ -1187,34 +1441,9 @@ If EXCLUDE-CHILDREN, only retrieve sibling boxes."
                            (with-slots (primary) box primary)))
   (oset match :locations (append (with-slots (locations) match locations)
                                  (with-slots (locations) box locations)))
-  (let ((world (org-real--get-world match)))
-    (mapc
-     (lambda (next)
-       (if (not (org-real--find-matching next world))
-           (org-real--add-next next match)))
-     (org-real--next box))))
-
-(cl-defmethod org-real--merge-into ((from org-real-box) (to org-real-box))
-  "Merge FROM box into TO box."
-  (let (match-found)
-    (mapc
-     (lambda (from-box)
-       (let ((match (org-real--find-matching from-box to)))
-         (while (and (not match) (slot-boundp from-box :rel-box))
-           (setq from-box (with-slots (rel-box) from-box rel-box))
-           (setq match (org-real--find-matching from-box to)))
-         (when match
-           (setq match-found t)
-           (org-real--add-matching from-box match))))
-     (org-real--primary-boxes from))
-    (unless match-found
-      (let ((all-from-children (with-slots (children hidden-children) from
-                                 (append (org-real--get-all children)
-                                         (org-real--get-all 
hidden-children)))))
-        (with-slots ((to-children children) (to-behind behind)) to
-          (if (= 1 (length all-from-children))
-              (org-real--flex-add (car all-from-children) to)
-            (org-real--flex-add from to)))))))
+  (mapc
+   (lambda (next) (org-real--add-next next match))
+   (org-real--next box)))
 
 (cl-defmethod org-real--add-next ((next org-real-box)
                                   (prev org-real-box)
@@ -1235,28 +1464,32 @@ If FORCE-VISIBLE, show the box regardless of
        (prev-in-front in-front)
        (prev-on-top on-top))
       prev
-    (with-slots ((siblings children) (hidden-siblings hidden-children)) parent
-      (with-slots
-          (rel
-           rel-box
-           extra-data
-           (next-level level)
-           (next-y y-order)
-           (next-x x-order)
-           (next-behind behind)
-           (next-in-front in-front)
-           (next-on-top on-top))
-          next
-        (let* ((next-boxes (org-real--next next))
-               (partitioned (seq-group-by
-                             (lambda (next-next)
-                               (with-slots (rel) next-next
-                                 (if (member rel '("in" "on" "behind" "in 
front of" "on top of"))
-                                     'children
-                                   'siblings)))
-                             next-boxes))
-               (children-boxes (alist-get 'children partitioned))
-               (sibling-boxes (alist-get 'siblings partitioned)))
+    (with-slots
+        (rel
+         rel-box
+         extra-data
+         (next-level level)
+         (next-y y-order)
+         (next-x x-order)
+         (next-behind behind)
+         (next-in-front in-front)
+         (next-on-top on-top))
+        next
+      (let* ((next-boxes (org-real--next next))
+             (partitioned (seq-group-by
+                           (lambda (next-next)
+                             (with-slots (rel) next-next
+                               (if (member rel org-real-children-prepositions)
+                                   'children
+                                 'siblings)))
+                           next-boxes))
+             (children-boxes (alist-get 'children partitioned))
+             (sibling-boxes (alist-get 'siblings partitioned)))
+        (if-let ((match (org-real--find-matching next prev)))
+            (mapc
+             (lambda (next-next)
+               (org-real--add-next next-next match))
+             (org-real--next next))
           (setq extra-data partitioned)
           (cond
            ((member rel '("to the left of" "to the right of"))
@@ -1272,8 +1505,7 @@ If FORCE-VISIBLE, show the box regardless of
                                  (lambda (sibling)
                                    (with-slots (y-order) sibling
                                      (= y-order prev-y)))
-                                 (append (org-real--get-all siblings)
-                                         (org-real--get-all 
hidden-siblings)))))
+                                 (org-real--get-children parent 'all))))
               (mapc
                (lambda (sibling)
                  (with-slots (x-order) sibling
@@ -1290,8 +1522,7 @@ If FORCE-VISIBLE, show the box regardless of
                                       (lambda (sibling)
                                         (with-slots (in-front on-top) sibling
                                           (not (or in-front on-top))))
-                                      (append (org-real--get-all siblings)
-                                              (org-real--get-all 
hidden-siblings))))))
+                                      (org-real--get-children parent 'all)))))
               (if (string= rel "above")
                   (setq next-y (- (apply 'min 0 sibling-y-orders) 1))
                 (setq next-y (+ 1 (apply 'max 0 sibling-y-orders))))))
@@ -1305,41 +1536,30 @@ If FORCE-VISIBLE, show the box regardless of
                                          (with-slots (in-front on-top) child
                                            (and (eq next-in-front in-front)
                                                 (eq next-on-top on-top))))
-                                       (append (org-real--get-all children)
-                                               (org-real--get-all 
hidden-children)))))))
+                                       (org-real--get-children prev 'all))))))
             (setq next-behind prev-behind))
            ((member rel '("in" "on" "behind"))
             (setq next-level (+ 1 prev-level))
             (setq next-behind prev-behind)))
           (if (not (slot-boundp next :name)) (setq next-level 0))
           (oset next :rel-box prev)
-          (let* ((visible (or force-visible (= 0 org-real--visibility) (<= 
next-level org-real--visibility))))
-            (cond
-             ((member rel '("in front of" "on top of"))
-              (oset next :parent prev)
-              (if visible
-                  (setq children (org-real--push children next))
-                (setq hidden-children (org-real--push hidden-children next))))
-             ((member rel '("in" "on" "behind"))
-              
-              (org-real--flex-add next prev))
-             (t
-              (oset next :parent parent)
-              (if visible
-                  (setq siblings (org-real--push siblings next))
-                (setq hidden-siblings (org-real--push hidden-siblings next)))))
-            (if children-boxes
-                (oset next :expand-children
-                      '(lambda (box)
-                         (mapc
-                          (lambda (child) (org-real--add-next child box))
-                          (alist-get 'children (oref box :extra-data))))))
-            (if sibling-boxes
-                (oset next :expand-siblings
-                      '(lambda (box)
-                         (mapc
-                          (lambda (sibling) (org-real--add-next sibling box t))
-                          (alist-get 'siblings (oref box 
:extra-data))))))))))))
+          (if (member rel org-real-children-prepositions)
+              (if (member rel org-real-flex-prepositions)
+                  (org-real--flex-add next prev)
+                (org-real--add-child prev next force-visible))
+            (org-real--add-child parent next force-visible))
+          (if children-boxes
+              (oset next :expand-children
+                    '(lambda (box)
+                       (mapc
+                        (lambda (child) (org-real--add-next child box))
+                        (alist-get 'children (oref box :extra-data))))))
+          (if sibling-boxes
+              (oset next :expand-siblings
+                    '(lambda (box)
+                       (mapc
+                        (lambda (sibling) (org-real--add-next sibling box t))
+                        (alist-get 'siblings (oref box :extra-data)))))))))))
 
 (cl-defmethod org-real--flex-add ((box org-real-box)
                                   (parent org-real-box))
@@ -1351,20 +1571,13 @@ characters if possible."
   (let* ((world (org-real--get-world parent))
          (cur-width (org-real--get-width world)))
     (org-real--make-dirty world)
-    (with-slots
-        ((siblings children)
-         (hidden-siblings hidden-children)
-         (parent-level level)
-         (parent-behind behind))
-        parent
+    (with-slots ((parent-level level) (parent-behind behind)) parent
       (let* ((level (+ 1 parent-level))
-             (visible (or (= 0 org-real--visibility) (<= level 
org-real--visibility)))
              (all-siblings (seq-filter
                             (lambda (sibling)
                               (with-slots (in-front on-top) sibling
                                 (not (or in-front on-top))))
-                            (append (org-real--get-all siblings)
-                                    (org-real--get-all hidden-siblings))))
+                            (org-real--get-children parent 'all)))
              (last-sibling (and all-siblings
                                 (seq-reduce
                                  (lambda (max sibling)
@@ -1378,12 +1591,9 @@ characters if possible."
                                  all-siblings
                                  (org-real-box :y-order -1.0e+INF)))))
         (oset box :flex t)
-        (oset box :parent parent)
         (oset box :behind parent-behind)
         (org-real--apply-level box level)
-        (if visible
-            (setq siblings (org-real--push siblings box))
-          (setq hidden-siblings (org-real--push hidden-siblings box)))
+        (org-real--add-child parent box)
         (when last-sibling
           (with-slots
               ((last-sibling-y y-order)
@@ -1398,75 +1608,67 @@ characters if possible."
                 (oset box :x-order 0)))))))))
 
 (cl-defmethod org-real--flex-adjust ((box org-real-box))
-  "Adjust BOX x and y orders to try to fit world within `org-real-flex-width'."
+  "Adjust BOX x and y orders to try to fit BOX within `org-real-flex-width'."
   (let ((cur-width (org-real--get-width box))
         new-width)
-    (org-real--flex-adjust-helper box)
+    (org-real--flex-adjust-helper box box)
     (setq new-width (org-real--get-width box))
     (while (and (< new-width cur-width)
                 (> new-width org-real-flex-width))
       (setq cur-width new-width)
-      (org-real--flex-adjust-helper box)
+      (org-real--flex-adjust-helper box box)
       (setq new-width (org-real--get-width box)))))
 
-(cl-defmethod org-real--flex-adjust-helper ((box org-real-box))
-  "Adjust BOX x and y orders to try to fit world within `org-real-flex-width'."
-  (with-slots (children flex parent) box
+(cl-defmethod org-real--flex-adjust-helper ((box org-real-box) (world 
org-real-box))
+  "Adjust BOX x and y orders to try to fit WORLD within `org-real-flex-width'."
+  (with-slots (flex parent) box
     (when flex
-      (let* ((world (org-real--get-world box))
-             (cur-width (org-real--get-width world)))
+      (let ((cur-width (org-real--get-width world)))
         (when (> cur-width org-real-flex-width)
           (let ((left (org-real--get-left box))
                 (width (org-real--get-width box)))
             (when (> (+ left width) org-real-flex-width)
-              (with-slots ((siblings children) (hidden-siblings 
hidden-children)) parent
-                (org-real--make-dirty world)
-                (when-let* ((all-siblings (seq-filter
-                                           (lambda (sibling)
-                                             (with-slots (in-front on-top) 
sibling
-                                               (not (or in-front on-top))))
-                                           (append (org-real--get-all siblings)
-                                                   (org-real--get-all 
hidden-siblings))))
-                            (last-sibling (seq-reduce
-                                           (lambda (max sibling)
-                                             (with-slots ((max-x x-order) 
(max-y y-order)) max
-                                               (with-slots
-                                                   ((sibling-x x-order)
-                                                    (sibling-y y-order))
+              (org-real--make-dirty world)
+              (when-let* ((all-siblings (seq-filter
+                                         (lambda (sibling)
+                                           (with-slots (in-front on-top) 
sibling
+                                             (not (or in-front on-top))))
+                                         (org-real--get-children parent)))
+                          (last-sibling (seq-reduce
+                                         (lambda (max sibling)
+                                           (with-slots ((max-x x-order) (max-y 
y-order)) max
+                                             (with-slots
+                                                 ((sibling-x x-order)
+                                                  (sibling-y y-order))
+                                                 sibling
+                                               (if (> sibling-y max-y)
                                                    sibling
-                                                 (if (> sibling-y max-y)
+                                                 (if (and (= max-y sibling-y) 
(> sibling-x max-x))
                                                      sibling
-                                                   (if (and (= max-y 
sibling-y) (> sibling-x max-x))
-                                                       sibling
-                                                     max)))))
-                                           all-siblings
-                                           (org-real-box :y-order -1.0e+INF))))
-                  (with-slots
-                      ((last-sibling-y y-order)
-                       (last-sibling-x x-order))
-                      last-sibling
-                    (oset box :y-order last-sibling-y)
-                    (oset box :x-order (+ 1 last-sibling-x))
-                    (let ((when-last (org-real--get-width world)))
-                      (when (> when-last org-real-flex-width)
-                        (org-real--make-dirty world)
-                        (oset box :y-order (+ 1 last-sibling-y))
-                        (oset box :x-order 0)
-                        (let ((when-new-row (org-real--get-width world)))
-                          (when (>= when-new-row when-last)
-                            (org-real--make-dirty world)
-                            (oset box :y-order last-sibling-y)
-                            (oset box :x-order (+ 1 
last-sibling-x))))))))))))))
-    (mapc 'org-real--flex-adjust-helper (org-real--get-all children))))
+                                                   max)))))
+                                         all-siblings
+                                         (org-real-box :y-order -1.0e+INF))))
+                (with-slots
+                    ((last-sibling-y y-order)
+                     (last-sibling-x x-order))
+                    last-sibling
+                  (oset box :y-order last-sibling-y)
+                  (oset box :x-order (+ 1 last-sibling-x))
+                  (let ((when-last (org-real--get-width world)))
+                    (when (> when-last org-real-flex-width)
+                      (org-real--make-dirty world)
+                      (oset box :y-order (+ 1 last-sibling-y))
+                      (oset box :x-order 0)
+                      (let ((when-new-row (org-real--get-width world)))
+                        (when (>= when-new-row when-last)
+                          (org-real--make-dirty world)
+                          (oset box :y-order last-sibling-y)
+                          (oset box :x-order (+ 1 last-sibling-x))))))))))))))
+  (mapc
+   (lambda (child)
+     (org-real--flex-adjust-helper child world))
+   (org-real--get-children box)))
 
-(cl-defmethod org-real--apply-level ((box org-real-box) level)
-  "Apply LEVEL to BOX and update all of its children."
-  (oset box :level level)
-  (with-slots (children hidden-children) box
-    (mapc
-     (lambda (child) (org-real--apply-level child (+ 1 level)))
-     (append (org-real--get-all children)
-             (org-real--get-all hidden-children)))))
 
 (cl-defmethod org-real--add-headline (headline
                                       (parent org-real-box))
@@ -1475,23 +1677,43 @@ characters if possible."
     (with-current-buffer (marker-buffer (car locations))
       (let* ((partitioned (seq-group-by
                            (lambda (h)
-                             (let ((child-rel (or (org-entry-get 
(org-element-property :begin h) "REL") "in")))
-                               (if (member child-rel '("in" "on" "behind" "in 
front of" "on top of"))
+                             (let ((child-rel (or (org-entry-get
+                                                   (org-element-property 
:begin h)
+                                                   "REL")
+                                                  "in")))
+                               (if (member child-rel 
org-real-children-prepositions)
                                    'children
                                  'siblings)))
                            (cddr headline)))
              (children (alist-get 'children partitioned))
              (siblings (alist-get 'siblings partitioned))
-             (pos (org-element-property :begin headline))
-             (rel (or (org-entry-get pos "REL") "in"))
-             (level (if (member rel '("in" "on" "behind" "in front of" "on top 
of"))
+             (pos (goto-char (org-element-property :begin headline)))
+             (columns (org-columns--collect-values))
+             (max-column-length (apply 'max 0
+                                       (mapcar
+                                        (lambda (column)
+                                          (length (cadr (car column))))
+                                        columns)))
+             (rel (or (org-entry-get nil "REL") "in"))
+             (level (if (member rel org-real-children-prepositions)
                         (+ 1 parent-level)
                       parent-level))
-             (box (org-real-box :name (org-element-property :title headline)
+             (name (org-element-property :title headline))
+             (box (org-real-box :name (if (string-match org-link-bracket-re 
name)
+                                          (match-string 2 name)
+                                        name)
                                 :rel rel
                                 :level level
                                 :rel-box parent
                                 :parent parent
+                                :metadata (mapconcat
+                                           (lambda (column)
+                                             (format
+                                              (concat "%" (number-to-string 
max-column-length) "s : %s")
+                                              (cadr (car column))
+                                              (cadr column)))
+                                           columns
+                                           "\n")
                                 :locations (list (set-marker (point-marker) 
pos))
                                 :in-front (string= rel "in front of")
                                 :on-top (string= rel "on top of")
@@ -1545,68 +1767,67 @@ characters if possible."
                        (line-number-at-pos)))
       (move-to-column (+ left 1 org-real-padding-x)))))
 
-;;;; Org real mode buttons
-
-(defun org-real--jump-other-window (box)
-  "Jump to location of link for BOX in other window."
-  (with-slots (locations) box
-    (lambda ()
-      (interactive)
-      (let ((first (car locations)))
-        (object-remove-from-list box :locations first)
-        (object-add-to-list box :locations first t))
-      (let* ((marker (car locations))
-             (buffer (marker-buffer marker))
-             (pos (marker-position marker)))
-        (save-selected-window
-          (switch-to-buffer-other-window buffer)
-          (goto-char pos))))))
-
-(defun org-real--jump-to (box)
-  "Jump to the first occurrence of a link for BOX in the same window."
-  (with-slots (locations) box
-    (lambda ()
-      (interactive)
-      (let* ((marker (car locations))
-             (buffer (marker-buffer marker))
-             (pos (marker-position marker)))
-        (if-let ((window (get-buffer-window buffer)))
-            (select-window window)
-          (switch-to-buffer buffer))
-        (goto-char pos)))))
-
-(defun org-real--jump-all (box)
-  "View all occurrences of links from BOX in the same window."
-  (with-slots (locations) box
-    (lambda ()
-      (interactive)
-      (let* ((size (/ (window-height) (length locations)))
-             (marker (car locations)))
-        (or (<= window-min-height size)
-            (error "To many buffers to visit simultaneously"))
-        (switch-to-buffer (marker-buffer marker))
-        (goto-char (marker-position marker))
-        (dolist (marker (cdr locations))
-          (select-window (split-window nil size))
-          (switch-to-buffer (marker-buffer marker))
-          (goto-char (marker-position marker)))))))
-
-(cl-defmethod org-real--create-button-keymap ((box org-real-box))
-  "Create a keymap for a button in Org Real mode.
-
-BOX is the box the button is being made for."
-  (with-slots (locations) box
-    (easy-mmode-define-keymap
-     (mapcar
-      (lambda (key) (cons (kbd (car key)) (cdr key)))
-      `(("TAB"       . ,(org-real--cycle-children box))
-        ("o"         . ,(org-real--jump-other-window box))
-        ("<mouse-1>" . ,(org-real--jump-to box))
-        ("RET"       . ,(org-real--jump-to box))
-        ("M-RET"     . ,(org-real--jump-all box)))))))
-
 ;;;; Utility expressions
 
+(defun org-real--tooltip (content)
+  "Show popup tooltip with CONTENT after `org-real-tooltip-timeout' idle time."
+  (when (and org-real-tooltips (not (string-empty-p content)))
+    (let ((marker (point-marker)))
+      (run-with-idle-timer
+       org-real-tooltip-timeout nil
+       (lambda ()
+         (if (and (eq (marker-buffer marker)
+                      (current-buffer))
+                  (eq (marker-position marker)
+                      (point)))
+             (org-real--tooltip-show content)))))))
+
+(defun org-real--tooltip-show (content)
+  "Show tooltip with CONTENT at point immediately."
+  (let* ((cur-line (line-number-at-pos))
+         (cur-column (current-column))
+         (min-line (save-excursion
+                    (goto-char (window-start))
+                    (line-number-at-pos)))
+         (max-column (+ (window-hscroll) (window-body-width)))
+         (rows (split-string content "\n"))
+         (height (length rows))
+         (width (+ 2 (min org-real-tooltip-max-width
+                          (apply 'max 0 (mapcar 'length rows)))))
+         (top (if (< (- cur-line 2 height) min-line)
+                  (+ cur-line 2)
+                (- cur-line 1 height)))
+         (left (if (> (+ cur-column width 1) max-column)
+                   (- max-column width 1)
+                 cur-column))
+         overlay overlays)
+    (dolist (str rows)
+      (let* ((pos (save-excursion
+                    (forward-line (- top (line-number-at-pos)))
+                    (let ((inhibit-read-only t))
+                      (move-to-column left t))
+                    (point)))
+             (remaining-chars (save-excursion
+                                (goto-char pos)
+                                (- (save-excursion
+                                     (end-of-line)
+                                     (current-column))
+                                   (current-column)))))
+        (setq str (format
+                   (concat " %-" (number-to-string (- width 2)) "s ")
+                   (truncate-string-to-width str org-real-tooltip-max-width 
nil nil t)))
+        (when (= 0 remaining-chars)
+          (save-excursion (goto-char pos) (let ((inhibit-read-only t)) (insert 
" ")))
+          (setq remaining-chars (+ 1 remaining-chars)))
+        (setq overlay (make-overlay pos (+ pos (min remaining-chars width))))
+        (overlay-put overlay 'face 'org-real-popup)
+        (overlay-put overlay 'display `((margin nil) ,str))
+        (push overlay overlays)
+        (setq top (+ top 1))))
+    (save-excursion (org-real-mode-recalculate-box-ring))
+    (push (read-event nil) unread-command-events)
+    (mapc 'delete-overlay overlays)))
+
 (defun org-real--find-last-index (pred sequence)
   "Return the index of the last element for which (PRED element) is non-nil in 
SEQUENCE."
   (let ((i (- (length sequence) 1)))
@@ -1639,7 +1860,7 @@ LINK is escaped with backslashes for inclusion in buffer."
         (org-link-escape link)
         (if description (format "[%s]" description) "")))))
 
-(defun org-real--parse-url (str marker)
+(defun org-real--parse-url (str &optional marker)
   "Parse STR into a list of plists.
 
 Returns a list of plists with a :name property and optionally a
@@ -1655,12 +1876,13 @@ set to the :loc slot of each box."
          (containers (mapcar
                       (lambda (token)
                         (let* ((location (split-string token "\\?"))
-                               (container (list :name (car location) :loc 
marker))
-                               (rel (and (string-match "&?rel=\\([^&]*\\)" 
(cadr location))
-                                         (match-string 1 (cadr location)))))
-                          (if rel
-                              (plist-put container :rel rel)
-                            container)))
+                               (rel (or (and (cadr location)
+                                             (string-match "&?rel=\\([^&]*\\)" 
(cadr location))
+                                             (match-string 1 (cadr location)))
+                                        "in")))
+                          (list :name (car location)
+                                :loc marker
+                                :rel rel)))
                       tokens)))
     (push (list :name host :loc marker) containers)))
 
@@ -1680,12 +1902,14 @@ set to the :loc slot of each box."
 
 (defun org-real--parse-headlines ()
   "Create an org real box from the current buffer's headlines."
+  (org-columns-get-format)
   (let* ((headlines (cddr (org-element-parse-buffer 'headline)))
          (filename (buffer-file-name))
          (title (or (concat (file-name-base filename) "." (file-name-extension 
filename))
                     "Document"))
          (world (org-real-box))
          (document (org-real-box :name title
+                                 :metadata ""
                                  :locations (list (point-min-marker)))))
     (org-real--flex-add document world)
     (mapc
@@ -1701,8 +1925,9 @@ set to the :loc slot of each box."
           (mapconcat
            (lambda (container)
              (concat (plist-get container :name)
-                     (when (plist-member container :rel)
-                       (concat "?rel=" (plist-get container :rel)))))
+                     (when-let ((rel (plist-get container :rel)))
+                       (if (not (string= "in" rel))
+                           (concat "?rel=" (plist-get container :rel))))))
            containers
            "/")))
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]