Ordenar una tabla de modo org con líneas horizontales

7

Tengo una tabla en la org-modeque tiene el siguiente formato:

| 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] |        |
|------------+-----------------+--------|

Pero quiero que la tabla esté formateada para que se vea así:

| 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 |
|------------+-----------------+--------|

Esta tabla se debe ordenar alfabéticamente. Entonces las dos últimas filas deberían ser las primeras. La separación con las líneas horizontales debe permanecer. Si hay diferentes palabras en columnas agrupadas, no importa cómo se ordenen. Entonces, el último grupo en la tabla anterior puede ser Barseguido por Bazo Bazseguido por Bar. ¿Cómo puedo hacer esto con Emacs org-mode?

Jens Kubieziel
fuente
1
Debería agregar un ejemplo de cómo desea que se vea la tabla, como: "Quiero esto ... Que se vea así ...".
Luke Shimkus
2
Realmente no entiendo las reglas de clasificación. ¿Solo desea ordenar en la primera columna dentro de cada sección y luego ordenar las secciones que dependen de la columna "nombre" de la primera fila de cada sección?
Rekado

Respuestas:

4

Desafortunadamente, org-modeno mantiene una estructura de datos alrededor que pueda usarse para realizar modificaciones que luego se reflejan directamente en la tabla, por lo que tenemos que arrastrar las líneas a una lista, hacer un procesamiento de la lista y luego convertir la lista resultante nuevamente en texto.

En general, el enfoque es el siguiente:

  • calcular los tamaños de grupo a partir de la información en org-table-hlines; esta variable contiene los números de fila de líneas horizontales
  • almacenar las líneas relacionadas con cada grupo en una lista y poner cada grupo en una lista

    '(("| Doe, John...|" "| Doe, Jane...|")
      ("| Foo, Pete...|")
      ("| Bar, Mary...|" "| Quux, Mike...|"))
    
  • ordena esta lista por el valor carde cada elemento, obteniendo algo como esto:

    '(("| Bar, Mary...|" "| Quux, Mike...|")
      ("| Doe, John...|" "| Doe, Jane...|")
      ("| Foo, Pete...|"))
    
  • luego reconstruya la tabla de esta lista iterando sobre cada grupo

EDITAR:

Aquí hay algo para comenzar. Es bastante incómodo, pero es solo para ilustrar la idea. (en rows-by-grouprealidad contiene duplicados, por lo que esto no es completamente correcto).

(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
fuente
Interesante. He estado pensando en cómo modificar tablas mediante programación y este es un buen comienzo.
Desnuda el