auto-update-daily-20260202

Advanced Emacs Lisp Workflows

This reference consolidates advanced Emacs Lisp development workflows that are used less frequently.

Core workflows (used frequently) are in separate workflow files:

  • Configure (workflows/Configure.md)
  • Script (workflows/Script.md)
  • Test (workflows/Test.md)
  • Lint (workflows/Lint.md)
  • Debug (workflows/Debug.md)

Package - Package Creation and Management

Create well-structured Emacs Lisp packages following modern conventions and MELPA requirements.

Package Types

Type Description Example
Single-file One .el file simple-mode.el
Multi-file Multiple .el files magit (magit.el, magit-*.el)
With dependencies Requires other packages Uses Package-Requires

Creating a Package

Step 1: Initialize with Eask

# Create package directory
mkdir my-package
cd my-package

# Initialize Eask project
eask init

# This creates:
# - Eask file
# - my-package.el (with template)
# - .gitignore

Step 2: Package File Structure

my-package.el (main file):

;;; my-package.el --- Brief description  -*- lexical-binding: t -*-

;; Copyright (C) 2025 Your Name

;; Author: Your Name <your.email@example.com>
;; Version: 0.1.0
;; Package-Requires: ((emacs "29.1"))
;; Keywords: convenience, tools
;; URL: https://github.com/yourusername/my-package
;; SPDX-License-Identifier: GPL-3.0-or-later

;; This file is not part of GNU Emacs.

;;; Commentary:

;; Longer description of what this package does.
;;
;; Usage:
;;
;;     (require 'my-package)
;;     (my-package-enable)
;;
;; Customization:
;;
;;     (setq my-package-option value)

;;; Code:

(require 'cl-lib)  ; If using cl-lib functions

(defgroup my-package nil
  "Customization group for my-package."
  :group 'tools
  :prefix "my-package-"
  :link '(url-link "https://github.com/yourusername/my-package"))

(defcustom my-package-enable-feature t
  "Whether to enable the feature."
  :type 'boolean
  :safe #'booleanp
  :group 'my-package)

;;;###autoload
(defun my-package-enable ()
  "Enable my-package."
  (interactive)
  (my-package-mode 1)
  (message "My Package enabled"))

(defvar my-package-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-c m t") #'my-package-toggle)
    map)
  "Keymap for `my-package-mode'.")

;;;###autoload
(define-minor-mode my-package-mode
  "Minor mode for my-package."
  :lighter " MyPkg"
  :keymap my-package-mode-map
  :global t
  :group 'my-package
  (if my-package-mode
      (my-package--enable)
    (my-package--disable)))

(defun my-package--enable ()
  "Internal function to enable my-package."
  ;; Setup code here
  )

(defun my-package--disable ()
  "Internal function to disable my-package."
  ;; Cleanup code here
  )

(provide 'my-package)
;;; my-package.el ends here

Step 3: Eask Configuration

Eask file:

(package "my-package"
         "0.1.0"
         "Brief description of my package")

(website-url "https://github.com/yourusername/my-package")
(keywords "convenience" "tools")

(package-file "my-package.el")

(script "test" "echo \"Run tests..\" && eask test ert")
(script "lint" "echo \"Linting..\" && eask lint package checkdoc")
(script "ci" "eask install-deps && eask compile && eask test && eask lint")

(source "gnu")
(source "melpa")

(depends-on "emacs" "29.1")
;; Add package dependencies here
;; (depends-on "dash")

(development
 (depends-on "ert-runner")
 (depends-on "package-lint"))

Step 4: Tests

my-package-test.el:

;;; my-package-test.el --- Tests for my-package  -*- lexical-binding: t -*-

(require 'ert)
(require 'my-package)

(ert-deftest my-package-test-enable ()
  "Test that enabling works."
  (my-package-mode 1)
  (should my-package-mode)
  (my-package-mode -1)
  (should-not my-package-mode))

(ert-deftest my-package-test-function ()
  "Test main functionality."
  ;; Your tests here
  (should (functionp 'my-package-enable)))

(provide 'my-package-test)
;;; my-package-test.el ends here

Step 5: README.md

# My Package

Brief description of what your package does.

## Installation

### MELPA

```elisp
(use-package my-package
  :ensure t)

Manual

Clone this repository and add to your load-path:

(add-to-list 'load-path "/path/to/my-package")
(require 'my-package)

Usage

;; Enable my-package
(my-package-enable)

;; Or use minor mode
(my-package-mode 1)

Configuration

(setq my-package-enable-feature nil)

License

GPL-3.0-or-later


## Multi-file Package

For larger packages with multiple files:

### Structure

my-package/ ├── my-package.el # Main entry point ├── my-package-core.el # Core functionality ├── my-package-ui.el # UI components ├── my-package-utils.el # Utilities ├── test/ │ ├── my-package-test.el │ └── my-package-core-test.el ├── Eask └── README.md


### Main File (my-package.el)

```elisp
;;; my-package.el --- Main entry point  -*- lexical-binding: t -*-

;; [Headers as before]

;;; Code:

(require 'my-package-core)
(require 'my-package-ui)
(require 'my-package-utils)

;;;###autoload
(defun my-package-setup ()
  "Set up my-package."
  (interactive)
  (my-package-core-initialize)
  (my-package-ui-setup))

(provide 'my-package)
;;; my-package.el ends here

Submodule (my-package-core.el)

;;; my-package-core.el --- Core functionality  -*- lexical-binding: t -*-

;; Copyright (C) 2025 Your Name
;; Author: Your Name <your.email@example.com>

;; This file is not part of GNU Emacs.

;;; Commentary:

;; Core functionality for my-package.

;;; Code:

(defun my-package-core-initialize ()
  "Initialize core functionality."
  ;; Implementation
  )

(provide 'my-package-core)
;;; my-package-core.el ends here

Package Headers Reference

Required Headers

;; Author: Your Name <email@example.com>
;; Version: 0.1.0
;; Package-Requires: ((emacs "29.1"))
;; Keywords: convenience tools
;; URL: https://github.com/user/repo

Optional Headers

;; Maintainer: Different Person <maintainer@example.com>
;; Created: 2025-01-01
;; SPDX-License-Identifier: GPL-3.0-or-later
;; Homepage: https://mypackage.example.com

Keywords

Standard keywords (for M-x finder-by-keyword):

  • abbrev - Abbreviation handling
  • calendar - Calendar and diary
  • comm - Communications
  • convenience - Convenience features
  • data - Data manipulation
  • docs - Documentation
  • emulations - Emulations of other editors
  • extensions - Emacs Lisp language extensions
  • faces - Fonts and faces
  • files - File handling
  • frames - Frame manipulation
  • games - Games
  • hardware - Hardware support
  • help - Help and documentation
  • hypermedia - Hypermedia
  • i18n - Internationalization
  • internal - Internal use
  • languages - Programming languages
  • lisp - Lisp support
  • local - Local customization
  • maint - Maintenance tools
  • mail - Mail handling
  • matching - Pattern matching
  • mouse - Mouse support
  • multimedia - Multimedia
  • news - News handling
  • outlines - Outline mode
  • processes - Process control
  • terminals - Terminal emulation
  • tex - TeX and friends
  • tools - Programming tools
  • unix - Unix features
  • vc - Version control
  • wp - Word processing

Common Patterns

Customization Group

(defgroup my-package nil
  "Customization for my-package."
  :group 'tools
  :prefix "my-package-"
  :link '(url-link :tag "GitHub" "https://github.com/user/my-package"))

(defcustom my-package-directory "~/.my-package"
  "Directory for my-package data."
  :type 'directory
  :group 'my-package)

(defcustom my-package-backends '(backend1 backend2)
  "List of backends to use."
  :type '(repeat (choice (const :tag "Backend 1" backend1)
                         (const :tag "Backend 2" backend2)))
  :group 'my-package)

Faces

(defface my-package-highlight
  '((t :inherit highlight))
  "Face for highlighted items."
  :group 'my-package)

(defface my-package-error
  '((t :inherit error))
  "Face for errors."
  :group 'my-package)

Hooks

(defvar my-package-mode-hook nil
  "Hook run after `my-package-mode' is enabled.")

(defvar my-package-before-process-hook nil
  "Hook run before processing.")

;; Run hooks
(run-hooks 'my-package-mode-hook)

Autoloads

;;;###autoload
(defun my-package-enable ()
  "Enable my-package globally."
  (interactive)
  (my-package-mode 1))

;;;###autoload
(add-to-list 'auto-mode-alist '("\\.mypkg\\'" . my-package-mode))

Development Workflow

1. Install Dependencies

eask install-deps

2. Byte Compile

eask compile

3. Run Tests

eask test ert

4. Lint

eask lint package
eask lint checkdoc

5. Package

eask package

Output: dist/my-package-0.1.0.tar

CI/CD with GitHub Actions

.github/workflows/test.yml:

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        emacs-version: ['29.1', '29.2', 'snapshot']

    steps:
      - uses: actions/checkout@v4

      - uses: jcs090218/setup-emacs@master
        with:
          version: ${{ matrix.emacs-version }}

      - uses: emacs-eask/setup-eask@master
        with:
          version: 'snapshot'

      - name: Install dependencies
        run: eask install-deps

      - name: Byte compile
        run: eask compile

      - name: Run tests
        run: eask test ert

      - name: Lint
        run: |
          eask lint package
          eask lint checkdoc

Versioning

Follow Semantic Versioning:

  • MAJOR: Incompatible API changes
  • MINOR: Add functionality (backwards-compatible)
  • PATCH: Bug fixes (backwards-compatible)

Example: 1.2.3 → MAJOR.MINOR.PATCH

Update Version

# In my-package.el header
;; Version: 1.0.0

# In Eask
(package "my-package" "1.0.0" "Description")

# Create git tag
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0

Common Issues

Package-Requires Format

;; Correct
;; Package-Requires: ((emacs "29.1") (dash "2.19.1"))

;; Wrong - no spaces
;; Package-Requires: ((emacs "29.1")(dash "2.19.1"))

;; Wrong - single dep not in list
;; Package-Requires: (emacs "29.1")

Lexical Binding

Always use:

;;; my-package.el --- Description  -*- lexical-binding: t -*-

Provide Statement

Must match filename:

;; File: my-package.el
(provide 'my-package)  ; Correct

;; File: my-package.el
(provide 'my-pkg)  ; Wrong!

Best Practices

  1. Use lexical binding: ;;; -*- lexical-binding: t -*-
  2. Follow naming conventions: All symbols prefixed with package name
  3. Complete headers: All required headers present
  4. Autoloads: Mark entry points with ;;;###autoload
  5. Tests: Write tests for all functionality
  6. Documentation: Complete docstrings for all public functions
  7. Version control: Use git, tag releases
  8. CI: Set up automated testing
  9. CHANGELOG: Maintain version history
  10. License: Include GPL-compatible license

Resources


Publish - Publishing to MELPA/ELPA

Publish Emacs Lisp packages to MELPA, GNU ELPA, or NonGNU ELPA.

Package Archives

Archive Requirements Review Target Audience
MELPA Public Git repo Community review Most packages
MELPA Stable Git tags Same as MELPA Stable releases
GNU ELPA Copyright assignment FSF review GNU project packages
NonGNU ELPA Free license FSF review Non-GNU free software

Requirements

  1. Public Git repository: GitHub, GitLab, SourceHut, etc.
  2. Package quality:
    • Passes package-lint
    • Passes checkdoc
    • Byte-compiles without warnings
  3. Documentation: README with usage instructions
  4. License: Free software license (GPL recommended)
  5. Tests: Recommended but not required

Step 1: Prepare Package

# Lint package
eask lint package

# Check documentation
eask lint checkdoc

# Byte compile
eask compile

# Run tests
eask test ert

# All checks pass? Continue!

Step 2: Create MELPA Recipe

Fork MELPA repository:

git clone https://github.com/melpa/melpa.git
cd melpa
git checkout -b add-my-package

Create recipe file recipes/my-package:

(my-package :fetcher github
            :repo "username/my-package")

Recipe Options:

;; GitHub
(my-package :fetcher github
            :repo "username/my-package"
            :files ("*.el" "dir/*.el"))

;; GitLab
(my-package :fetcher gitlab
            :repo "username/my-package")

;; SourceHut
(my-package :fetcher sourcehut
            :repo "username/my-package")

;; Git (generic)
(my-package :fetcher git
            :url "https://example.com/my-package.git"
            :branch "main")

;; With specific files
(my-package :fetcher github
            :repo "username/my-package"
            :files ("*.el" "lisp/*.el"
                    (:exclude "lisp/test-*.el")))

;; Multi-file package
(my-package :fetcher github
            :repo "username/my-package"
            :files (:defaults "extensions/*.el"))

Step 3: Test Recipe Locally

# In MELPA directory
make recipes/my-package

# Test installation
make sandbox INSTALL=my-package

# Clean up
make clean

Step 4: Submit Pull Request

git add recipes/my-package
git commit -m "Add my-package recipe"
git push origin add-my-package

Create PR at https://github.com/melpa/melpa/pulls

Step 5: Address Review Feedback

MELPA maintainers will review:

  • Recipe correctness
  • Package quality
  • License
  • Documentation

Common feedback:

  • Fix package-lint warnings
  • Improve docstrings
  • Add missing headers
  • Simplify recipe

Step 6: Approval and Publication

Once approved:

  • PR is merged
  • Package builds automatically
  • Available in MELPA within 24 hours

MELPA Stable

Requirements

Same as MELPA, plus:

  • Git tags for releases
  • Semantic versioning

Create Release

# Tag release
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0

Recipe

(my-package :fetcher github
            :repo "username/my-package"
            :version-regexp "v\\([0-9.]+\\)")  ; Optional

MELPA Stable automatically uses tags.

GNU ELPA

Requirements

  1. Copyright assignment: For packages >300 lines
  2. License: GPL-compatible
  3. Code quality: High standards
  4. No external dependencies: Prefer built-in features

Process

  1. Email proposal: Send to emacs-devel@gnu.org

    Subject: [ELPA] New package: my-package
    
    I would like to submit my-package to GNU ELPA.
    
    Description: [Brief description]
    Repository: [Git URL]
    License: GPL-3.0-or-later
    
    [Additional details]
    
  2. Copyright assignment:

    • If >300 lines, complete FSF copyright assignment
    • Process takes 2-4 weeks
    • Forms available from FSF
  3. Code review:

    • FSF maintainers review code
    • May request changes
    • Higher standards than MELPA
  4. Integration:

    • Package added to GNU ELPA
    • Automatically built and published

NonGNU ELPA

Requirements

  1. Free license: GPL, MIT, Apache, etc.
  2. No copyright assignment: Unlike GNU ELPA
  3. Code quality: Good standards
  4. No proprietary dependencies

Process

  1. Email proposal: Send to emacs-devel@gnu.org

    Subject: [NonGNU ELPA] New package: my-package
    
    I would like to submit my-package to NonGNU ELPA.
    
    Description: [Brief description]
    Repository: [Git URL]
    License: MIT
    
    The package provides [features]...
    
  2. Review: Less strict than GNU ELPA

  3. Integration: Added to NonGNU ELPA repository

Version Management

Semantic Versioning

Follow SemVer:

  • MAJOR: Incompatible API changes (1.0.0 → 2.0.0)
  • MINOR: New features, backwards-compatible (1.0.0 → 1.1.0)
  • PATCH: Bug fixes, backwards-compatible (1.0.0 → 1.0.1)

Update Version

;; In package file header
;; Version: 1.2.3

;; In Eask
(package "my-package" "1.2.3" "Description")

Create Release

# Update version in files
# Update CHANGELOG.md

git add .
git commit -m "Bump version to 1.2.3"
git tag -a v1.2.3 -m "Release version 1.2.3"
git push origin main
git push origin v1.2.3

CHANGELOG

Maintain CHANGELOG.md:

# Changelog

All notable changes to this project will be documented in this file.

## [Unreleased]

### Added
- Feature in development

## [1.2.0] - 2025-01-15

### Added
- New command `my-package-export`
- Support for custom backends

### Changed
- Improved performance of parsing
- Updated documentation

### Fixed
- Bug in file handling

## [1.1.0] - 2025-01-01

### Added
- Initial public release

Package Distribution

Create Package Tarball

# With Eask
eask package

# Output: dist/my-package-1.0.0.tar

# Manual
tar -cf my-package-1.0.0.tar my-package.el my-package-utils.el README.md

Test Package Installation

;; Install local package
M-x package-install-file RET /path/to/my-package-1.0.0.tar RET

;; Or from directory
M-x package-install-file RET /path/to/package-directory RET

Post-Publication

Monitor Issues

  • Watch GitHub issues
  • Respond to bug reports
  • Merge pull requests

Update Package

# Fix bugs, add features
git commit -am "Fix issue #123"
git push

# MELPA rebuilds automatically
# No PR needed for updates

Deprecation

If deprecating package:

;; Add to package file
(make-obsolete 'my-package-old-function
               'my-package-new-function
               "1.5.0")

(define-obsolete-function-alias
  'my-old-function
  'my-new-function
  "1.5.0")

(define-obsolete-variable-alias
  'my-old-var
  'my-new-var
  "1.5.0")

Quality Checklist

Before publishing:

Code Quality

  • All functions have docstrings
  • All variables have docstrings
  • Lexical binding enabled
  • No byte-compile warnings
  • package-lint passes
  • checkdoc passes

Documentation

  • README with installation and usage
  • CHANGELOG with version history
  • License file (GPL-3.0-or-later recommended)
  • Code comments where needed

Testing

  • Tests cover main functionality
  • Tests pass
  • CI configured (GitHub Actions)

Package Metadata

  • All required headers present
  • Package-Requires correct
  • Keywords appropriate
  • URL points to repository

Repository

  • .gitignore includes build artifacts
  • Clean git history
  • Tagged releases
  • Issues/PR templates (optional)

Common Issues

Recipe Rejected

Wrong :files:

;; Bad - includes test files
(my-package :fetcher github
            :repo "user/my-package"
            :files ("*.el"))

;; Good - excludes tests
(my-package :fetcher github
            :repo "user/my-package"
            :files (:defaults (:exclude "test-*.el")))

Package Fails to Build

Check MELPA build log:

Common causes:

  • Missing dependencies
  • Byte-compile errors
  • Wrong file paths

Version Mismatch

;; Version in package file
;; Version: 1.0.0

;; Must match git tag
git tag v1.0.0

Best Practices

  1. Start with MELPA: Easiest to publish
  2. Tag releases: For MELPA Stable
  3. Semantic versioning: Clear version scheme
  4. Maintain CHANGELOG: Document changes
  5. Respond to issues: Help users
  6. Keep dependencies minimal: Easier maintenance
  7. Test thoroughly: Before each release
  8. Document well: README and docstrings
  9. Follow conventions: MELPA guidelines
  10. CI/CD: Automate testing

Resources


Document - Documentation and Docstrings

Write comprehensive documentation for Emacs Lisp packages: docstrings, README, and Info manuals.

Docstrings

Function Docstrings

(defun my-package-process-file (file &optional verbose callback)
  "Process FILE and return the result.

FILE should be a path to a readable file.  Optional argument
VERBOSE, when non-nil, enables progress messages.  Optional
argument CALLBACK is called with the result when processing
completes.

The function reads FILE, processes its contents, and returns
a list of processed items.  If FILE cannot be read, returns nil.

Example usage:

  (my-package-process-file \"input.txt\" t)
  (my-package-process-file \"data.csv\" nil #'my-callback)

Returns a list of the form (ITEM1 ITEM2 ...), or nil if FILE
cannot be processed.

Signals an error if FILE does not exist or is not readable.

See also `my-package-process-directory'."
  ...)

Docstring Guidelines

  1. First line: Complete sentence, under 80 characters
  2. Argument names: UPPERCASE when mentioned
  3. Blank line: After first sentence (for summary)
  4. Return value: Document what function returns
  5. Signals: Document errors that may be raised
  6. Examples: Show typical usage
  7. See also: Reference related functions

Variable Docstrings

(defvar my-package-timeout 30
  "Timeout in seconds for network operations.

This value controls how long to wait before giving up on
network requests.  A value of 0 means no timeout.

Changing this value affects all future operations but does
not impact currently running operations.")

(defvar my-package--internal-state nil
  "Internal state for my-package.
This variable should not be modified directly.")

Custom Variables

(defcustom my-package-auto-save t
  "Whether to automatically save after operations.

When non-nil, files are automatically saved after processing.
When nil, you must manually save changes.

You can also set this locally per buffer using:

  (setq-local my-package-auto-save nil)"
  :type 'boolean
  :safe #'booleanp
  :group 'my-package)

(defcustom my-package-backends '(backend1 backend2)
  "List of backends to use for processing.

Each backend should be a symbol recognized by my-package.
Backends are tried in order until one succeeds.

Available backends:
  backend1 - Fast but limited
  backend2 - Slower but more features
  backend3 - Requires external program"
  :type '(repeat (choice (const :tag "Backend 1" backend1)
                         (const :tag "Backend 2" backend2)
                         (const :tag "Backend 3" backend3)))
  :group 'my-package)

Package Commentary

;;; my-package.el --- Brief description  -*- lexical-binding: t -*-

;; [Headers...]

;;; Commentary:

;; My Package provides tools for processing data files.
;;
;; Features:
;;
;; - Process multiple file formats
;; - Batch processing support
;; - Customizable backends
;; - Integration with other tools
;;
;; Basic usage:
;;
;;     (require 'my-package)
;;     (my-package-enable)
;;     (my-package-process-file "data.csv")
;;
;; Configuration:
;;
;;     (setq my-package-auto-save nil)
;;     (setq my-package-timeout 60)
;;
;; For more information, see the Info manual:
;;
;;     C-h i m My Package RET
;;
;; Or visit the project page:
;;
;;     https://github.com/user/my-package

;;; Code:

README.md

Complete README Structure

# My Package

[![MELPA](https://melpa.org/packages/my-package-badge.svg)](https://melpa.org/#/my-package)
[![CI](https://github.com/user/my-package/workflows/CI/badge.svg)](https://github.com/user/my-package/actions)

Brief one-sentence description of what the package does.

## Features

- Feature 1
- Feature 2
- Feature 3

## Installation

### MELPA

```elisp
(use-package my-package
  :ensure t
  :config
  (my-package-enable))

Manual

Clone this repository:

git clone https://github.com/user/my-package.git

Add to your init.el:

(add-to-list 'load-path "/path/to/my-package")
(require 'my-package)

Usage

Basic Usage

;; Enable globally
(my-package-mode 1)

;; Or in specific buffers
(add-hook 'text-mode-hook #'my-package-mode)

Commands

Command Description Keybinding
my-package-enable Enable the package -
my-package-process Process current buffer C-c m p
my-package-export Export to file C-c m e

Configuration

;; Set timeout
(setq my-package-timeout 60)

;; Choose backend
(setq my-package-backend 'backend2)

;; Disable auto-save
(setq my-package-auto-save nil)

Customization

All options can be customized via:

M-x customize-group RET my-package RET

Key options:

  • my-package-timeout - Operation timeout in seconds
  • my-package-auto-save - Automatically save after processing
  • my-package-backend - Which backend to use

Examples

Example 1: Process File

(my-package-process-file "data.csv" t)

Example 2: Batch Processing

(my-package-process-directory "~/data/" "\\.csv$")

Troubleshooting

Package doesn’t load

Make sure the package is in your load-path:

(add-to-list 'load-path "/path/to/my-package")

Command not found

Ensure the package is loaded:

(require 'my-package)

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new features
  4. Ensure all tests pass
  5. Submit a pull request

License

GPL-3.0-or-later

Acknowledgments

  • Thanks to contributor1
  • Thanks to contributor2

## Info Manual

### Create Manual

**doc/my-package.texi**:

```texinfo
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename my-package.info
@settitle My Package Manual
@documentencoding UTF-8
@c %**end of header

@copying
This manual is for My Package version 1.0.

Copyright @copyright{} 2025 Your Name

@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation.
@end quotation
@end copying

@titlepage
@title My Package Manual
@subtitle For version 1.0
@author Your Name
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@contents

@node Top
@top My Package

My Package provides tools for processing data files.

@menu
* Introduction::      What is My Package?
* Installation::      Installing the package
* Usage::             How to use the package
* Configuration::     Customization options
* Index::             Complete index
@end menu

@node Introduction
@chapter Introduction

My Package helps you process data files efficiently.

@node Installation
@chapter Installation

Install from MELPA:

@lisp
(use-package my-package
  :ensure t)
@end lisp

@node Usage
@chapter Usage

@section Basic Usage

Enable the package:

@lisp
(my-package-enable)
@end lisp

@section Commands

@table @code
@item my-package-enable
Enable the package globally.

@item my-package-process-file
Process a single file.
@end table

@node Configuration
@chapter Configuration

@defvar my-package-timeout
Timeout in seconds for operations.
@end defvar

@defvar my-package-auto-save
Whether to auto-save after processing.
@end defvar

@node Index
@unnumbered Index

@printindex cp

@bye

Build Info Manual

# Generate info file
makeinfo doc/my-package.texi -o my-package.info

# View
info -f my-package.info

# Install system-wide
sudo install-info my-package.info /usr/share/info/dir

Include in Package

;; In Eask
(package-file "my-package.el")
(files "my-package.el" "my-package-utils.el" "my-package.info")

CHANGELOG.md

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- New feature in development

## [1.2.0] - 2025-01-15

### Added
- New command `my-package-export` for exporting data
- Support for CSV format
- Interactive completion for file selection

### Changed
- Improved performance of file processing (30% faster)
- Updated documentation with more examples
- Refactored backend system for extensibility

### Deprecated
- `my-package-old-function` - Use `my-package-new-function` instead

### Removed
- Removed support for deprecated format X

### Fixed
- Fixed bug in error handling (#42)
- Fixed memory leak in batch processing (#45)
- Corrected documentation typo (#48)

### Security
- Fixed potential security issue with file paths

## [1.1.0] - 2025-01-01

### Added
- Initial public release
- Basic file processing
- Customization options

## [1.0.0] - 2024-12-15

### Added
- Initial development version

Documentation Tools

checkdoc

;; Check docstrings
M-x checkdoc

;; Check current buffer
M-x checkdoc-current-buffer

;; Fix automatically
M-x checkdoc-eval-current-buffer

package-lint

# Check documentation
eask lint checkdoc

Best Practices

Docstrings

  1. Complete sentences: Start with capital, end with period
  2. First line summary: Complete thought, under 80 chars
  3. Document arguments: Use UPPERCASE for arg names
  4. Document return: What does function return?
  5. Document signals: What errors can occur?
  6. Examples: Show typical usage
  7. Cross-references: Link to related functions

README

  1. Clear title: What is the package?
  2. Installation: Simple, copy-paste instructions
  3. Usage examples: Show common use cases
  4. Configuration: List key options
  5. Screenshots: If UI-heavy (optional)
  6. Badges: MELPA, CI status
  7. Contributing: How to help
  8. License: Clear license information

Info Manual

  1. Comprehensive: More detail than README
  2. Organized: Logical chapter structure
  3. Examples: Lots of code examples
  4. Index: Complete index for searching
  5. Cross-references: Link related sections

Resources