Sortieren einer Org-Modus-Tabelle mit horizontalen Linien

7

Ich habe eine Tabelle, org-modedie das folgende Format hat:

| Name       | email           | number |
|------------+-----------------+--------|
| Doe, John  | [email protected] |      7 |
| Doe, Jane  | [email protected] |        |
|------------+-----------------+--------|
| Foo, Pete  | [email protected]  |      5 |
|------------+-----------------+--------|
| Bar, Mary  | [email protected]  |      3 |
| Quux, Mike | [email protected] |        |
|------------+-----------------+--------|

Ich möchte jedoch, dass die Tabelle so formatiert wird:

| Name       | email           | number |
|------------+-----------------+--------|
| Bar, Mary  | [email protected]  |      3 |
| Quux, Mike | [email protected] |        |
|------------+-----------------+--------|
| Doe, John  | [email protected] |      7 |
| Doe, Jane  | [email protected] |        |
|------------+-----------------+--------|
| Foo, Pete  | [email protected]  |      5 |
|------------+-----------------+--------|

Diese Tabelle sollte alphabetisch sortiert sein. Die letzten beiden Zeilen sollten also die ersten sein. Der Abstand zu den horizontalen Linien sollte erhalten bleiben. Wenn in gruppierten Spalten unterschiedliche Wörter enthalten sind, spielt es keine Rolle, wie sie sortiert sind. Der letzten Gruppe in der obigen Tabelle kann also entweder Barfolgen Bazoder Bazfolgen Bar. Wie kann ich das mit Emacs machen org-mode?

Jens Kubieziel
quelle
1
Sie sollten ein Beispiel hinzufügen, wie die Tabelle aussehen soll: "Ich möchte, dass das ... so aussieht ...".
Luke Shimkus
2
Ich verstehe die Sortierregeln nicht wirklich. Möchten Sie nur nach der ersten Spalte in jedem Abschnitt sortieren und dann die Abschnitte in Abhängigkeit von der Spalte "Name" der ersten Zeile jedes Abschnitts sortieren?
rekado

Antworten:

4

Leider wird org-modekeine Datenstruktur beibehalten, die zum Ausführen von Änderungen verwendet werden kann, die dann direkt in der Tabelle wiedergegeben werden. Daher müssen wir die Zeilen in eine Liste schlürfen, eine Listenverarbeitung durchführen und die resultierende Liste dann wieder in konvertieren Text.

Im Allgemeinen lautet der Ansatz wie folgt:

  • Berechnen Sie die Gruppengrößen aus Informationen in org-table-hlines; Diese Variable enthält die Zeilennummern der horizontalen Linien
  • Speichern Sie die Zeilen für jede Gruppe in einer Liste und fügen Sie jede Gruppe in eine Liste ein

    '(("| Doe, John...|" "| Doe, Jane...|")
      ("| Foo, Pete...|")
      ("| Bar, Mary...|" "| Quux, Mike...|"))
    
  • Sortieren Sie diese Liste nach dem Wert carjedes Elements, um Folgendes zu erhalten:

    '(("| Bar, Mary...|" "| Quux, Mike...|")
      ("| Doe, John...|" "| Doe, Jane...|")
      ("| Foo, Pete...|"))
    
  • Erstellen Sie dann die Tabelle aus dieser Liste neu, indem Sie jede Gruppe durchlaufen

BEARBEITEN:

Hier ist etwas, um Ihnen den Einstieg zu erleichtern. Es ist ziemlich umständlich, aber es dient nur zur Veranschaulichung der Idee. ( rows-by-groupenthält tatsächlich Duplikate, daher ist dies nicht vollständig korrekt.)

(defun my-org-sort-lines ()
  (interactive)
  (org-table-recalculate 'iterate)
  (let* ((hlines org-table-hlines)
         (rows-by-group (let* ((xs (cdr (append hlines nil)))
                               (xs2 (mapcar #'1+ xs))
                               (ys (mapcar #'1- (cdr (copy-sequence xs)))))
                          (mapcar* #'list (setcdr (last xs2) xs2) ys)))
         ;; fetch rows and store as nested list
         (groups (mapcar (lambda (group)
                           (mapcar (lambda (row-id)
                                     (goto-line row-id)
                                     (beginning-of-line)
                                     (let ((beg (point)))
                                       (end-of-line)
                                       (buffer-substring beg (point))))
                                   group))
                           rows-by-group))
         ;; sort groups by first row
         (sorted (sort groups (lambda (a b)
                                (string-lessp (car a) (car b))))))

    ;; remove existing table rows and rebuild from group list
    (goto-char (org-table-begin))
    (next-line 1)
    (kill-region (point) (org-table-end))
    (mapcar (lambda (group)
              (insert "|---")(org-table-recalculate)(next-line)
              (mapcar (lambda (row)
                        (insert row)(newline)) group))
            sorted))
  (insert "|---")
  (org-table-recalculate))
rekado
quelle
Interessant. Ich habe darüber nachgedacht, wie Tabellen programmgesteuert geändert werden können, und dies ist ein guter Anfang.
Undostres