Replace LaTeX and Org-mode include filenames with chapter titles and rename the files on disk — all in one keystroke in Emacs, of course, the ultimate text editor where magic happens.
- Problem addressed and its solution
- Features
- Requirements
- Installation
- Usage
- Customization
- Running the Tests
- Code Coverage
- Project Layout
- Contributing
- License
When you split a book or thesis into one file per chapter, the filenames in your \include{}, \input{}, or #+INCLUDE: statements quickly drift out of sync with the actual chapter titles. rename-chapter fixes that: place your cursor on the include line, call M-x rename-chapter, and the package will
- Open the referenced
.texor.orgfile, - Extract the
\chapter{}title (or the first Org heading, or#+TITLE:), - Strip whitespace from the title,
- Rename the file on disk, and
- Update the include statement in your buffer.
- LaTeX support — parses both
\include{path}and\input{path}. - Org-mode support — parses
#+INCLUDE: "path". - Subdirectory-aware — paths like
./Contents/ch03_methodsare handled correctly; the directory prefix is preserved. - Multiple title sources — searches
\chapter{}first, then top-level Org headings (* …), then#+TITLE:. - Customizable separator — strip whitespace entirely (
MaterialsandMethods), replace with underscores (Materials_and_Methods), or hyphens (Materials-and-Methods). - Safe — refuses to overwrite an existing file with the target name.
- Emacs 27.1 or later (for
string-empty-p,cl-libbuilt-in, andlexical-bindingdefaults).
No external dependencies are needed, except ert to run the tests and undercover to report coverage, which can be done via the Makefile.
git clone https://github.com/MooersLab/rename-chapter.git ~/path/to/rename-chapterAdd to your init file (~/.emacs.d/init.el or ~/.emacs):
(add-to-list 'load-path "~/path/to/rename-chapter")
(require 'rename-chapter)
(define-key LaTeX-mode-map (kbd "C-c C-r") #'rename-chapter)
(define-key org-mode-map (kbd "C-c C-r") #'rename-chapter)(use-package rename-chapter
:load-path "~/path/to/rename-chapter"
:bind (:map LaTeX-mode-map
("C-c C-r" . rename-chapter)
:map org-mode-map
("C-c C-r" . rename-chapter)))(use-package rename-chapter
:straight (:host github :repo "MooersLab/rename-chapter")
:bind (:map LaTeX-mode-map
("C-c C-r" . rename-chapter)
:map org-mode-map
("C-c C-r" . rename-chapter)))Copy rename-chapter.el somewhere on your load-path and add (require 'rename-chapter) to your init file.
-
Open your main
.texor.orgfile — the one with the include statements. -
Place your cursor anywhere on the line that contains the include:
\include{./Contents/ch03_methods}
or
#+INCLUDE: "./Contents/chapter1.org" -
Run
M-x rename-chapter(or press your keybinding, e.g.C-c C-r). -
The package reads
ch03_methods.tex, finds\chapter{Materials and Methods}, and then:- renames
./Contents/ch03_methods.tex→./Contents/MaterialsandMethods.tex - updates the line to
\include{./Contents/MaterialsandMethods}
- renames
| Style | Before | After |
|---|---|---|
| LaTeX | \include{./Contents/ch03_methods} |
\include{./Contents/MaterialsandMethods} |
| LaTeX | \input{intro} |
\input{IntroductiontoCrystallography} |
| Org | #+INCLUDE: "./Contents/chapter1.org" |
#+INCLUDE: "./Contents/IntroductiontoCrystallography.org" |
Two user options control how whitespace in the chapter title is replaced. You can change them interactively with M-x customize-group RET rename-chapter or set them in your init file.
| Variable | Default | Effect |
|---|---|---|
rename-chapter-strip-regexp |
"\\s-+" |
Regexp matching characters to remove |
rename-chapter-strip-replacement |
"" |
Replacement string |
;; Default: strip all whitespace
;; "Materials and Methods" → "MaterialsandMethods"
;; Underscores instead of removal:
(setq rename-chapter-strip-replacement "_")
;; "Materials and Methods" → "Materials_and_Methods"
;; Hyphens:
(setq rename-chapter-strip-replacement "-")
;; "Materials and Methods" → "Materials-and-Methods"The test suite uses Emacs' built-in ERT framework. Every test creates its own temporary directory with fixture files, so no manual setup is needed and nothing on your real filesystem is touched.
# Run the full test suite
make test
# Byte-compile with warnings as errors (lint)
make lint
# Run tests with code coverage (requires undercover.el)
make coverage
# Both lint + test
make allYou can point to a specific Emacs binary:
make test EMACS=/usr/local/bin/emacs-29M-x ert RET t RET
This runs every test whose name matches the pattern t (i.e., all tests). To run a single test:
M-x ert RET rc-test-integration-latex-include RET
| Category | Count | Description |
|---|---|---|
| Title extraction | 5 | \chapter{}, Org heading, #+TITLE:, missing title, priority ordering |
| File resolution | 5 | Bare names, extensions, subdirectories, missing files |
| Line parsing | 5 | \include, \input, #+INCLUDE:, no-subdir variant, error on plain text |
| Path building | 5 | LaTeX ± extension, Org ± extension, no subdirectory |
| Title cleaning | 4 | Default strip, underscore, hyphen, no-op |
| Integration | 5 | Full round-trip for LaTeX include, input, Org include, Org #+TITLE, custom replacement |
| Error paths | 4 | No include on line, file not found, no title in file, target already exists |
| Total | 33 |
Coverage is provided by undercover.el, which instruments rename-chapter.el at load time, runs the ERT suite, and writes an LCOV report.
Install undercover once from MELPA:
M-x package-install RET undercover RET
You also need lcov if you want an HTML report (optional):
# macOS
brew install lcov
# Debian / Ubuntu
sudo apt install lcovmake coverageThis produces coverage/lcov.info. If undercover is installed somewhere other than the default package-user-dir, pass the path:
make coverage UNDERCOVER_LOAD_PATH=~/.emacs.d/elpa/undercover-0.8.1make coverage-html
open coverage/html/index.html # macOS
xdg-open coverage/html/index.html # LinuxThe HTML report shows per-file and per-line hit counts, making it easy to spot untested branches.
On GitHub Actions (or any CI that undercover recognizes), edit test/coverage-helper.el and set :send-report t. undercover will then post results directly to Coveralls or Codecov. See the undercover.el README for provider-specific setup.
rename-chapter/
├── rename-chapter.el # The package (single file)
├── test/
│ ├── rename-chapter-test.el # ERT test suite (33 tests)
│ └── coverage-helper.el # undercover.el bootstrap for coverage
├── Makefile # compile, test, lint, coverage targets
├── .gitignore # Ignores *.elc and coverage/
├── README.md # This file
└── LICENSE # GPL-3.0-or-later
- Alpha
- Not in MELPA yet.
- Code works.
- All 33 tests pass.
Contributions are welcome. Please open an issue to discuss significant changes before submitting a pull request.
- Fork the repository.
- Create a feature branch:
git checkout -b my-feature. - Make sure
make allpasses before committing. - Submit a pull request.
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.
| Version | Changes | Date |
|---|---|---|
| Version 0.1.0 | Initial commit of working code. | 2026 March 4 |
- NIH: R01 CA242845.
- NIH: R01 AI088011.
- NIH: P30 CA225520 (PI: R. Mannel).
- NIH: P20 GM103640 and P30 GM145423 (PI: A. West).