Go to file
copilot-swe-agent[bot] 73f65e294b Optimize function naming and add object parameter support
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
2025-12-12 03:34:13 +00:00
LICENSE Initial commit 2025-10-13 00:13:38 +08:00
README.md Optimize function naming and add object parameter support 2025-12-12 03:34:13 +00:00
tp-tests.el Optimize function naming and add object parameter support 2025-12-12 03:34:13 +00:00
tp.el Optimize function naming and add object parameter support 2025-12-12 03:34:13 +00:00

tp.el - Text Properties Library for Emacs

A powerful text properties manipulation library with an innovative layer system

FeaturesInstallationQuick StartAPI ReferenceLayer System


tp.el provides a convenient and unified API for manipulating Emacs text properties. Inspired by ov.el for overlays, tp.el offers:

  • Unified API: All property-setting functions work on both strings and buffers
  • Layer System: Stack multiple property sets on the same text region
  • Pattern Matching: Apply properties to text matching strings or regexps

Features

  • Unified Object Support: Functions like tp-put, tp-match, tp-regexp work on both strings and buffers
  • Innovative Layer System: Stack, rotate, and manage multiple layers of properties
  • Layer Groups: Define reusable sets of related layers
  • Search & Navigation: Find and navigate through propertized text
  • Pattern Matching: Apply properties to string/regexp matches
  • Clean API: Consistent naming and calling conventions

Requirements

  • Emacs 28.1+ (uses object-intervals function)
  • dash.el (list manipulation utilities)

Installation

;; Add to your load-path
(add-to-list 'load-path "/path/to/tp")
(require 'tp)

Or with use-package:

(use-package tp
  :load-path "/path/to/tp")

Quick Start

Setting Properties

;; On current buffer
(tp-put 1 10 'face 'bold 'help-echo "Hello!")

;; On a string
(tp-put "Hello World" 0 5 'face 'bold)
;; => #("Hello World" 0 5 (face bold))

;; Using a property list
(tp-put 1 10 '(face bold help-echo "test"))

Getting Properties

;; Get specific property
(tp-get 5 'face)  ; => bold

;; Get all properties at point
(tp-at 5)  ; => (face bold help-echo "Hello!")

Pattern Matching

;; Apply properties to all occurrences of "TODO" in buffer
(tp-match "TODO" 'face 'warning)

;; Apply to string
(tp-match "world" "Hello world world" 'face 'bold)
;; => #("Hello world world" 6 11 (face bold) 12 17 (face bold))

;; Using regexp
(tp-regexp "\\b[0-9]+\\b" 'face 'font-lock-number-face)

API Reference

Core Property Functions

tp-put - Set Text Properties

Set text properties on a string or buffer region.

;; Buffer (current buffer)
(tp-put START END PROPERTY VALUE ...)
(tp-put START END '(PROPERTY VALUE ...))

;; String or Buffer object
(tp-put OBJECT START END PROPERTY VALUE ...)
(tp-put OBJECT START END '(PROPERTY VALUE ...))

Examples:

;; Set face on buffer region
(tp-put 1 10 'face 'bold)  ; => (1 . 10)

;; Set multiple properties
(tp-put 1 10 'face 'bold 'help-echo "Click me")

;; Set properties on a string
(setq my-string (tp-put "Hello World" 0 5 'face 'italic))
;; => #("Hello World" 0 5 (face italic))

;; Properties as a list
(tp-put 1 10 '(face bold mouse-face highlight))

tp-get - Get Property Value

(tp-get POSITION PROPERTY &optional OBJECT)

Get the value of PROPERTY at POSITION.

Examples:

(tp-get 5 'face)           ; Get from current buffer
(tp-get 0 'face my-string) ; Get from string

tp-at - Get All Properties

(tp-at &optional POINT OBJECT)

Get all text properties at POINT as a plist.

Examples:

(tp-at 5)  ; => (face bold help-echo "test")
(tp-at 0 my-string)  ; Get from string

tp-remove - Remove Property

(tp-remove START END PROPERTY &optional OBJECT)

Remove a specific property from a region.

Examples:

(tp-remove 1 10 'face)  ; Remove face property

tp-remove-list - Remove Multiple Properties

(tp-remove-list START END PROPERTIES &optional OBJECT)

Remove multiple properties at once.

Examples:

(tp-remove-list 1 10 '(face help-echo mouse-face))

tp-clear - Clear All Properties

(tp-clear &optional START END OBJECT)

Clear all text properties from a region.

Examples:

(tp-clear 1 10)     ; Clear region
(tp-clear)          ; Clear entire buffer

Propertize Functions

tp-propertize - Create Propertized String

;; Create propertized string
(tp-propertize STRING PROPERTY VALUE ...)
(tp-propertize STRING '(PROPERTY VALUE ...))

;; Apply to region of object
(tp-propertize OBJECT START END PROPERTY VALUE ...)

Examples:

;; Simple usage - returns propertized string
(tp-propertize "Hello" 'face 'bold)
;; => #("Hello" 0 5 (face bold))

;; With property list
(tp-propertize "World" '(face italic help-echo "greeting"))

;; Apply to substring
(tp-propertize "Hello World" 6 11 'face 'underline)

tp-layer-propertize - Apply Layer to Object

(tp-layer-propertize OBJECT LAYER &optional START END)

Apply a predefined layer's properties to an object.

Examples:

;; Define a layer first
(tp-layer-define highlight '(face (:background "yellow")))

;; Apply to string
(tp-layer-propertize "Important" 'highlight)

;; Apply to substring
(tp-layer-propertize "Hello World" 'highlight 0 5)

;; Apply to buffer region
(tp-layer-propertize (current-buffer) 'highlight 1 10)

tp-group-propertize - Apply Layer Group

(tp-group-propertize OBJECT LAYER-GROUP &optional START END)

Apply all layers from a layer group to an object.


Pattern Matching Functions

tp-match - Match String

;; Buffer
(tp-match PATTERN PROPERTY VALUE ...)

;; String or Buffer object
(tp-match PATTERN OBJECT PROPERTY VALUE ...)

Set properties on all occurrences of a string pattern.

Examples:

;; In buffer - returns list of (START . END) pairs
(tp-match "TODO" 'face 'warning)
;; => ((10 . 14) (50 . 54) ...)

;; On string - returns modified string
(tp-match "o" "Hello World" 'face 'bold)
;; => #("Hello World" 4 5 (face bold) 7 8 (face bold))

tp-regexp - Match Regexp

;; Buffer
(tp-regexp PATTERN PROPERTY VALUE ...)

;; String or Buffer object
(tp-regexp PATTERN OBJECT PROPERTY VALUE ...)

Set properties on all matches of a regular expression.

Examples:

;; Highlight all numbers in buffer
(tp-regexp "[0-9]+" 'face 'font-lock-number-face)

;; On string
(tp-regexp "[A-Z]+" "Hello WORLD" 'face 'bold)
;; => #("Hello WORLD" 6 11 (face bold))

Search & Navigation Functions

tp-forward / tp-backward

(tp-forward PROPERTY &optional VALUE PREDICATE NOT-CURRENT)
(tp-backward PROPERTY &optional VALUE PREDICATE NOT-CURRENT)

Search forward/backward for text with PROPERTY.

Examples:

;; Find next text with 'marker property
(tp-forward 'marker)

;; Find next text where 'type equals 'heading
(tp-forward 'type 'heading)

tp-next / tp-prev

(tp-next &optional POINT PROPERTY VALUE)
(tp-prev &optional POINT PROPERTY VALUE)

Get the next/previous position with text properties.


tp-goto-next / tp-goto-prev

(tp-goto-next &optional PROPERTY VALUE)
(tp-goto-prev &optional PROPERTY VALUE)

Move point to next/previous text with PROPERTY.


tp-regions-map / tp-strings-map

(tp-regions-map FUNCTION PROPERTY &optional VALUE PREDICATE COLLECT)
(tp-strings-map FUNCTION PROPERTY &optional VALUE PREDICATE COLLECT)

Apply a function to all regions/strings with PROPERTY.

Examples:

;; Upcase all marked text
(tp-strings-map
 (lambda (str idx)
   (message "Found: %s at index %d" str idx))
 'marker)

Query Functions

tp-in - Find Regions with Property

(tp-in PROPERTY &optional VALUE START END)

Get all regions with PROPERTY in current buffer.

Examples:

;; Get all regions with 'marker property
(tp-in 'marker)
;; => ((1 5 (marker t ...)) (10 15 (marker t ...)))

;; Filter by value
(tp-in 'type 'heading)

tp-all - Get All Propertized Regions

(tp-all &optional START END)

Get all regions with any text properties.


tp-intervals - Get Property Intervals

(tp-intervals START END &optional OBJECT)

Get all text property intervals in a region.


tp-empty-p - Check for Properties

(tp-empty-p OBJECT)

Return t if OBJECT has no text properties.


tp-plist - Get Merged Properties

(tp-plist START END &optional OBJECT)

Get a merged plist of all properties in a region.


The Layer System

The layer system is tp.el's innovative feature that allows stacking multiple sets of properties on the same text region. Only the top layer is visible, but lower layers are preserved and can be revealed through rotation or pinning.

Layer Concept

┌─────────────────────────────┐
│   TOP LAYER (visible)       │  ← What you see
├─────────────────────────────┤
│   Middle Layer (hidden)     │  ← Preserved
├─────────────────────────────┤
│   Bottom Layer (hidden)     │  ← Preserved
└─────────────────────────────┘

Layer Definition Functions

tp-layer-define - Define a Layer

(tp-layer-define NAME PROPERTIES)

Define a named layer with properties.

Examples:

(tp-layer-define highlight
  '(face (:background "yellow" :foreground "black")))

(tp-layer-define error
  '(face (:background "red" :foreground "white")
    help-echo "Error!"))

(tp-layer-define info
  '(face (:background "blue" :foreground "white")))

tp-group-define - Define Layer Group

(tp-group-define NAME
  LAYER1 PROPERTIES1
  LAYER2 PROPERTIES2
  ...)

Define a group of related layers.

Examples:

(tp-group-define status-colors
  status-ok      '(face (:foreground "green"))
  status-warning '(face (:foreground "orange"))
  status-error   '(face (:foreground "red")))

tp-layer-props / tp-group-props

(tp-layer-props LAYER-NAME)
(tp-group-props GROUP-NAME)

Get properties for a layer or all layers in a group.


tp-layer-undefine / tp-group-undefine

(tp-layer-undefine NAME)
(tp-group-undefine NAME)

Remove layer or group definition.


tp-layer-reset

(tp-layer-reset)

Clear all layer and group definitions.


Layer Manipulation Functions

tp-layer-push - Add Layer

(tp-layer-push START END NAME &optional OBJECT)

Push a layer to the top of the stack.

Examples:

(tp-layer-define base '(face default))
(tp-layer-define highlight '(face (:background "yellow")))

;; Push base layer first
(tp-layer-push 1 10 'base)

;; Push highlight on top (now visible)
(tp-layer-push 1 10 'highlight)

tp-layer-delete - Remove Layer

(tp-layer-delete START END NAME &optional OBJECT)

Delete a layer from anywhere in the stack.

Examples:

;; Remove the highlight layer
(tp-layer-delete 1 10 'highlight)
;; base layer is now visible

tp-layer-rotate - Cycle Layers

(tp-layer-rotate START END &optional OBJECT)

Rotate layers - top goes to bottom, next becomes visible.

Examples:

;; Stack: highlight (top) -> base (bottom)
(tp-layer-rotate 1 10)
;; Stack: base (top) -> highlight (bottom)

tp-layer-pin - Bring Layer to Top

(tp-layer-pin START END NAME &optional OBJECT)

Move a specific layer to the top.

Examples:

;; Make 'base the top layer
(tp-layer-pin 1 10 'base)

tp-layer-hide / tp-layer-show

(tp-layer-hide START END NAME &optional OBJECT)
(tp-layer-show START END NAME &optional OBJECT)

Hide layer (move to bottom) or show layer (move to top).


tp-layer-merge

(tp-layer-merge START END LAYER1 LAYER2 NEW-NAME &optional OBJECT)

Merge two layers into one new layer.


Layer Query Functions

tp-layer-list - List All Layers

(tp-layer-list START END &optional OBJECT)

Get list of all layer names in region.

Examples:

(tp-layer-list 1 10)  ; => (highlight base)

tp-layer-count

(tp-layer-count START END &optional OBJECT)

Count layers in region.


tp-layer-exists-p

(tp-layer-exists-p START END NAME &optional OBJECT)

Check if layer exists in region.


tp-layer-top

(tp-layer-top START END &optional OBJECT)

Get name of the top (visible) layer.


Practical Examples

Syntax Highlighting with Multiple Layers

;; Define layers for different highlighting purposes
(tp-layer-define code-base
  '(face font-lock-keyword-face))

(tp-layer-define code-error
  '(face (:underline (:color "red" :style wave))
    help-echo "Syntax error"))

(tp-layer-define code-debug
  '(face (:background "dark blue")))

;; Apply base highlighting
(tp-layer-push 1 100 'code-base)

;; Add error highlight on problematic code
(tp-layer-push 50 60 'code-error)

;; Toggle between error and normal view
(defun toggle-error-view ()
  (interactive)
  (tp-layer-rotate 50 60))

Status Indicator

(tp-group-define task-status
  status-todo     '(face (:foreground "gray"))
  status-progress '(face (:foreground "yellow"))
  status-done     '(face (:foreground "green")))

;; Cycle through statuses
(defun cycle-task-status ()
  (interactive)
  (tp-layer-rotate (line-beginning-position) (line-end-position)))

Temporary Highlights

(tp-layer-define temp-highlight
  '(face (:background "yellow")))

(defun flash-region (start end)
  "Flash a region temporarily."
  (tp-layer-push start end 'temp-highlight)
  (run-with-timer 0.5 nil
                  (lambda ()
                    (tp-layer-delete start end 'temp-highlight))))

Aliases

For convenience, tp.el provides these aliases:

Alias Original Function
tp-set tp-put
tp-layer-properties tp-layer-props
tp-layer-group-define tp-group-define
tp-layer-group-properties tp-group-props
tp-layer-group-propertize tp-group-propertize
tp-layer-group-undefine tp-group-undefine

License

GNU General Public License v2 or later.


Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.


tp.el - Making text properties powerful and easy to use