Classificando uma tabela de modo organizacional com linhas horizontais

7

Eu tenho uma tabela na org-modequal tem o seguinte 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] |        |
|------------+-----------------+--------|

Mas quero que a tabela seja formatada para ficar assim:

| 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 tabela deve ser classificada em ordem alfabética. Portanto, as duas últimas linhas devem ser as primeiras. A separação com as linhas horizontais deve permanecer. Se houver palavras diferentes nas colunas agrupadas, não importa como elas serão classificadas. Portanto, o último grupo da tabela acima pode ser Barseguido Bazou Bazseguido por Bar. Como posso fazer isso com o Emacs org-mode?

Jens Kubieziel
fonte
11
Você deve adicionar um exemplo de como você deseja que a tabela fique, como: "Eu quero isso ... É assim ...".
Luke Shimkus
2
Eu realmente não entendo as regras de classificação. Deseja classificar apenas a primeira coluna em cada seção e, em seguida, classificar as seções dependentes da coluna "nome" da primeira linha de cada seção?
rekado

Respostas:

4

Infelizmente, org-modenão mantém uma estrutura de dados ao redor que possa ser usada para executar modificações que são refletidas diretamente na tabela; portanto, temos que agrupar as linhas em uma lista, fazer algum processamento de lista e converter a lista resultante novamente em texto.

Em geral, a abordagem é a seguinte:

  • calcular os tamanhos dos grupos a partir das informações em org-table-hlines; essa variável mantém os números de linha das linhas horizontais
  • armazene as linhas relacionadas a cada grupo em uma lista e coloque cada grupo em uma lista

    '(("| Doe, John...|" "| Doe, Jane...|")
      ("| Foo, Pete...|")
      ("| Bar, Mary...|" "| Quux, Mike...|"))
    
  • classifique esta lista pelo valor carde cada item, obtendo algo como isto:

    '(("| Bar, Mary...|" "| Quux, Mike...|")
      ("| Doe, John...|" "| Doe, Jane...|")
      ("| Foo, Pete...|"))
    
  • em seguida, recrie a tabela dessa lista iterando sobre cada grupo

EDITAR:

Aqui está algo para você começar. É um pouco estranho, mas é apenas para ilustrar a ideia. ( rows-by-groupna verdade, contém duplicatas, portanto, isso não está completamente correto.)

(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
fonte
Interessante. Estive pensando em como modificar tabelas programaticamente e este é um bom começo.
undostres