在emacs org mode中如何冻结表格行

11

在 org mode 中,有没有类似 Excel 的方式可以冻结行?

我想要冻结表格的标题,这样当我向下移动页面时,标题仍然显示。


3
我能想到的一件事是将缓冲区水平拆分,并将表格顶部保留在顶部缓冲区,同时在底部缓冲区中进行操作。否则,我不知道有任何特定的Org-mode解决方案。 - user797257
我不相信在Emacs中支持冻结窗口的部分功能。 - Jonathan Jin
另一个伪解决方案:使用M-<Up Arrow>或M-<Down Arrow>可以将表格中的一行向上或向下拖动。您可以1)保存缓冲区2)从标题行开始向下拖动,直到您喜欢并检查列3)完成后恢复缓冲区以将标题行放回原处。如果您想在检查时进行编辑,则此“解决方案”不是很好。 - user2548343
2个回答

3

现在有一个名为org-table-sticky-header的工具,似乎正是您想要的:“用于显示org-mode表格粘性标题的辅助模式”。

相关的Emacs配置文件是“org-table-sticky-header.el”,其内容如下:

;;; org-table-sticky-header.el --- Sticky header for org-mode tables  -*- lexical-binding: t; -*-

;; Copyright (C) 2017  Junpeng Qiu

;; Author: Junpeng Qiu <qjpchmail@gmail.com>
;; Keywords: extensions
;; Version: 0.1.0
;; Package-Requires: ((org "8.2.10") (emacs "24.4"))

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;;                      ______________________________

;;                       ORG-TABLE-STIKCY-HEADER-MODE

;;                               Junpeng Qiu
;;                      ______________________________


;; Table of Contents
;; _________________

;; 1 Overview
;; 2 Usage
;; 3 Demo


;; [[file:https://melpa.org/packages/org-table-sticky-header-badge.svg]]

;; A minor mode to show the sticky header for org-mode tables.


;; [[file:https://melpa.org/packages/org-table-sticky-header-badge.svg]]
;; https://melpa.org/#/org-table-sticky-header


;; 1 Overview
;; ==========

;;   Similar to `semantic-stickyfunc-mode', this package uses the header
;;   line to show the table header when it is out of sight.


;; 2 Usage
;; =======

;;   To install manually:
;;   ,----
;;   | (add-to-list 'load-path "/path/to/org-table-sticky-header.el")
;;   `----

;;   `M-x org-table-sticky-header-mode' to enable the minor mode in an
;;   org-mode buffer.

;;   To automatically enable the minor mode in all org-mode buffers, use
;;   ,----
;;   | (add-hook 'org-mode-hook 'org-table-sticky-header-mode)
;;   `----


;; 3 Demo
;; ======

;;   [./screenshots/demo.gif]

;;; Code:

(require 'org)
(require 'org-table)

(defvar org-table-sticky-header--last-win-start -1)
(defvar org-table-sticky-header--old-header-line-format nil)

(defun org-table-sticky-header--is-header-p (line)
(not
(or (string-match "^ *|-" line)
(let ((cells (split-string line "|"))
(ret t))
(catch 'break
(dolist (c cells ret)
(unless (or (string-match "^ *$" c)
(string-match "^ *<[0-9]+> *$" c)
(string-match "^ *<[rcl][0-9]*> *$" c))
(throw 'break nil))))))))

(defun org-table-sticky-header--table-real-begin ()
(save-excursion
(goto-char (org-table-begin))
(while (and (not (eobp))
(not (org-table-sticky-header--is-header-p
(buffer-substring-no-properties
(point-at-bol)
(point-at-eol)))))
(forward-line))
(point)))

(defun org-table-sticky-header-org-table-header-visible-p ()
(save-excursion
(goto-char org-table-sticky-header--last-win-start)
(>= (org-table-sticky-header--table-real-begin) (point))))

(defun org-table-sticky-header--get-line-prefix-width (line)
(let (prefix)
(and (bound-and-true-p org-indent-mode)
(setq prefix (get-text-property 0 'line-prefix line))
(string-width prefix))))

(defun org-table-sticky-header--get-visual-header (text visual-col)
(if (= visual-col 0)
text
(with-temp-buffer
(insert text)
(goto-char (point-min))
(while (> visual-col 0)
(when (string= (get-text-property (point) 'display) "=>")
(setq visual-col (1- visual-col)))
(move-point-visually 1)
(setq visual-col (1- visual-col)))
(buffer-substring (point) (point-at-eol)))))

(defun org-table-sticky-header-get-org-table-header ()
(let ((col (window-hscroll))
visual-header)
(save-excursion
(goto-char org-table-sticky-header--last-win-start)
(if (bobp)
""
(if (org-at-table-p 'any)
(goto-char (org-table-sticky-header--table-real-begin))
(forward-line -1))
(setq visual-header
(org-table-sticky-header--get-visual-header
(buffer-substring (point-at-bol) (point-at-eol))
col))
(remove-text-properties 0
(length visual-header)
'(face nil)
visual-header)
visual-header))))

(defun org-table-sticky-header--fetch-header ()
(if (org-table-sticky-header-org-table-header-visible-p)
(setq header-line-format org-table-sticky-header--old-header-line-format)
;; stole from `semantic-stickyfunc-mode'
(let ((line (org-table-sticky-header-get-org-table-header)))
(setq header-line-format
`(:eval (list
(propertize
" "
'display
'((space :align-to
,(or (org-table-sticky-header--get-line-prefix-width line)
0))))
,line))))))

(defun org-table-sticky-header--scroll-function (win start-pos)
(unless (= org-table-sticky-header--last-win-start start-pos)
(setq org-table-sticky-header--last-win-start start-pos)
(save-match-data
(org-table-sticky-header--fetch-header))))

(defun org-table-sticky-header--insert-delete-column ()
(if org-table-sticky-header-mode
(save-match-data
(org-table-sticky-header--fetch-header))))

(defun org-table-sticky-header--table-move-column (&optional left)
(if org-table-sticky-header-mode
(save-match-data
(org-table-sticky-header--fetch-header))))

;;;###autoload
(define-minor-mode org-table-sticky-header-mode
"Sticky header for org-mode tables."
nil " OTSH" nil
(if org-table-sticky-header-mode
(if (derived-mode-p 'org-mode)
(progn
(setq org-table-sticky-header--old-header-line-format header-line-format)
(add-hook 'window-scroll-functions
'org-table-sticky-header--scroll-function 'append 'local)
(advice-add 'org-table-delete-column :after #'org-table-sticky-header--insert-delete-column)
(advice-add 'org-table-insert-column :after #'org-table-sticky-header--insert-delete-column)
(advice-add 'org-table-move-column :after #'org-table-sticky-header--table-move-column)
(setq org-table-sticky-header--last-win-start (window-start))
(org-table-sticky-header--fetch-header))
(setq org-table-sticky-header-mode nil)
(error "Not in `org-mode'"))
(advice-remove 'org-table-delete-column #'org-table-sticky-header--insert-delete-column)
(advice-remove 'org-table-insert-column #'org-table-sticky-header--insert-delete-column)
(advice-remove 'org-table-move-column #'org-table-sticky-header--table-move-column)
(remove-hook 'window-scroll-functions 'org-table-sticky-header--scroll-function 'local)
(setq header-line-format org-table-sticky-header--old-header-line-format)))

(provide 'org-table-sticky-header)
;;; org-table-sticky-header.el ends here

可从以下位置获取:


1
请确保安装 org-table-sticky-header 而不是 org-sticky-header。 :) - Lorem Ipsum

3
我想到了两个选项。
  1. 最简单(虽然不太正式但很灵活)的解决方案是将窗口水平分割,并在两个窗口中显示相同的缓冲区。将顶部窗口调整大小以仅显示表格顶部,您可以独立滚动另一个窗口。由于它是共享缓冲区,所以列将对齐,完成后可以删除不需要的窗口。

  2. 您可以依靠emacs头行(http://www.emacswiki.org/emacs/HeaderLine)在org-table范围内时,在当前窗口顶部显示表格的第一行。通过像设置模式行一样设置header-line-format来实现这一点。这绝对是一种更干净的选择,但肯定是一种更复杂的解决方案。

以下是一个快速而简单的示例,适用于您:

(setq-local header-line-format
        (list '(:eval
            (save-excursion
              (org-table-goto-line 1)
              (substring (thing-at-point 'line t) 0 -1)))))

这里有一些类似的尝试:https://emacs.stackexchange.com/questions/774/preview-fields-in-org-table/1040#1040

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接