| .gitignore | ||
| LICENSE | ||
| README_CN.md | ||
| README.md | ||
| tp-tests.el | ||
| tp.el | ||
tp.el - Text Properties Library for Emacs
A powerful text properties manipulation library with an innovative property layer system
Features • Installation • Quick Start • API Reference • Property Layer System • 中文文档
Overview
tp.el is a library that comprehensively enhances Emacs text property manipulation. It is not just a simple wrapper around native text property APIs (like put-text-property, get-text-property), but provides many functional extensions that native functions do not have.
Inspired by ov.el for overlays, tp.el innovates in the following areas:
Core Innovations
- Unified API Parameter Conventions: All functions support multiple flexible calling patterns, working seamlessly with both strings and buffers
- Fine-grained Sub-property Operations: Support path-style access, modification, and deep merging of nested properties
- Innovative Property Layer System: Stack and manage multiple sets of properties on the same text region with layered control
- Pattern Matching Batch Operations: Batch apply properties via string or regular expression matching
- Enhanced Search & Navigation: Rich property search and traversal functionality
Features
Unified API Parameter Conventions
Native Emacs APIs have different functions and parameter orders for strings and buffers. tp.el unifies all of this:
- ✅ Three Calling Conventions: All core functions (
tp-set,tp-get,tp-remove, etc.) support three flexible calling patterns:;; 1. Current buffer (tp-set START END '(face bold)) ;; 2. Specific buffer or string (tp-set START END '(face bold) OBJECT) ;; 3. Entire string (flat properties) (tp-set STRING 'face 'bold 'help-echo "tip") - ✅ Unified Object Support: The same function works with both strings and buffers, no need to remember different APIs
Three Property Operation Semantics
Native APIs only have simple set and get. tp.el provides three clear operation semantics:
- ✅
tp-reset: Complete replacement - clears all existing properties, sets new ones - ✅
tp-set: Partial replacement - only replaces specified properties, preserves others - ✅
tp-add: Deep merge - intelligently merges nested properties instead of simple overwrite
;; Deep merge example
(tp-set 1 10 '(face (:foreground "red")))
(tp-add 1 10 '(face (:background "blue")))
;; Result: face is (:foreground "red" :background "blue")
;; Native API would completely overwrite, but tp-add merges intelligently
Fine-grained Sub-property Operations
This is functionality that native APIs completely lack. tp.el supports fine-grained reading, modification, and deletion of nested properties:
- ✅ Path-style Access: Access deeply nested property values through path syntax
;; Get nested properties (tp-get str 'face :underline :style) ; => wave (tp-at 5 '(face :box :color)) ; => "blue" ;; Get multiple nested keys (tp-get str 'face :underline '(:color :style)) ;; => ((:color "green" :style wave)) - ✅ Sub-property Deletion: Precisely remove specific keys from nested properties
;; Only delete :style from :underline, preserve :color (tp-remove 1 10 '(face :underline (:style))) - ✅ Deep Merge:
tp-addrecursively merges nested plist structures - ✅ Smart Face Merging: Symbol faces are automatically prepended to face lists, plist faces are deep merged
Innovative Property Layer System
This is tp.el's most innovative feature, completely unsupported by native Emacs. The property layer system allows stacking multiple sets of properties on the same text region:
- ✅ Property Layer Stack Concept: Multiple property layers stack like a stack, only the top layer is visible, lower layers are preserved
- ✅ Property Layer Definition & Reuse: Define reusable property layers and layer groups via
tp-define-layer - ✅ Rich Property Layer Operations:
- Placement:
tp-put-layer(specific position),tp-push-layer(top) - Deletion:
tp-delete-layer(by name/index),tp-pop-layer(top layer) - Movement:
tp-raise-layer(up/down),tp-rotate-layer(rotate),tp-pin-layer(pin to top),tp-switch-layer(swap) - Merging:
tp-merge-layers(merge specified layers),tp-flatten-layers(flatten all layers)
- Placement:
- ✅ Property Layer Queries:
tp-layer-list,tp-layer-count,tp-layer-exists-p,tp-layer-top
;; Property layer usage example
(tp-define-layer highlight (face (:background "yellow")))
(tp-define-layer error (face (:foreground "red")))
;; Stack multiple property layers
(tp-push-layer 1 10 'highlight)
(tp-push-layer 1 10 'error) ; error is now visible
;; Rotate display
(tp-rotate-layer 1 10) ; highlight is now visible
Pattern Matching & Batch Operations
Native APIs require manual searching and looping. tp.el provides convenient pattern matching functionality:
- ✅ String Matching:
tp-match-set,tp-match-reset,tp-match-add - ✅ Regexp Matching:
tp-regexp-set,tp-regexp-reset,tp-regexp-add - ✅ Three Semantic Variants: Each match type supports set/reset/add operation semantics
;; Highlight all TODOs
(tp-match-set "TODO" '(face warning))
;; Regexp match all numbers
(tp-regexp-set "[0-9]+" '(face font-lock-number-face))
;; Add properties with deep merge
(tp-match-add "TODO" '(face (:underline t)))
Enhanced Search & Navigation
- ✅ Range Search:
tp-searchreturns a list of all matching intervals - ✅ N-times Search:
tp-forward/tp-backwardsupport searching forward/backward N times - ✅ Search and Execute:
tp-forward-do/tp-backward-dosearch and execute function on matched text - ✅ Batch Transform:
tp-search-mapapplies transformation function to all matches
;; Search all markers
(tp-search my-string 'marker) ; => ((0 5 t) (12 17 t))
;; Upcase all marker text
(tp-search-map #'upcase my-string 'marker)
Requirements
- Emacs 28.1+ (uses
object-intervalsfunction) - 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")
API Reference
API Quick Reference
A complete overview of all tp.el functions organized by category:
Core Property Functions
| Function | Description |
|---|---|
tp-set |
Set text properties (replaces specified properties only) |
tp-reset |
Replace ALL text properties |
tp-add |
Add/merge properties with deep merge support |
tp-get |
Get property value(s) from range or string |
tp-at |
Get property value(s) at a single position |
tp-remove |
Remove a property or sub-property |
tp-clear |
Clear all text properties from a region |
Pattern Matching Functions
| Function | Description |
|---|---|
tp-match-set |
Set properties on string pattern matches |
tp-match-reset |
Reset all properties on string matches |
tp-match-add |
Add/merge properties on string matches |
tp-regexp-set |
Set properties on regexp matches |
tp-regexp-reset |
Reset all properties on regexp matches |
tp-regexp-add |
Add/merge properties on regexp matches |
Search & Navigation Functions
| Function | Description |
|---|---|
tp-search-forward |
Raw wrapper for text-property-search-forward |
tp-search-backward |
Raw wrapper for text-property-search-backward |
tp-forward |
Search forward N times for text with property (buffers and strings) |
tp-backward |
Search backward N times for text with property (buffers and strings) |
tp-forward-do |
Apply function to matched text for N forward matches (with optional start point) |
tp-backward-do |
Apply function to matched text for N backward matches (with optional start point) |
tp-search |
Search all matching properties in range or string |
tp-search-map |
Apply function to matched text for all matches |
Property Layer Definition Functions
| Function | Description |
|---|---|
tp-define-layer |
Define a layer or layer group |
tp-layer-props |
Get properties for a layer |
tp-group-props |
Get properties for all layers in a group |
tp-layer-undefine |
Remove layer definition |
tp-group-undefine |
Remove group definition |
tp-layer-reset |
Clear all layer/group definitions |
Property Layer Placement Functions
| Function | Description |
|---|---|
tp-put-layer |
Set layer at specific index position |
tp-push-layer |
Push layer to top of stack |
Property Layer Deletion Functions
| Function | Description |
|---|---|
tp-delete-layer |
Delete layer by name or index |
tp-pop-layer |
Remove top layer |
Property Layer Movement Functions
| Function | Description |
|---|---|
tp-raise-layer |
Move layer up/down by N positions |
tp-rotate-layer |
Cycle layers (top goes to bottom) |
tp-pin-layer |
Pin a layer to top (make visible) |
tp-switch-layer |
Swap positions of two layers |
Property Layer Merging Functions
| Function | Description |
|---|---|
tp-merge-layers |
Merge specified layers into a new layer |
tp-flatten-layers |
Flatten all layers into a single layer |
Property Layer Query Functions
| Function | Description |
|---|---|
tp-layer-list |
List all layer names in region |
tp-layer-count |
Count layers in region |
tp-layer-exists-p |
Check if layer exists in region |
tp-layer-top |
Get name of top (visible) layer |
Core Property Functions
tp-set - Set Text Properties
Set text properties on a string or buffer region. Replaces only the specified properties, preserving others.
;; Current buffer (properties as a list)
(tp-set START END '(PROPERTY VALUE ...))
;; Specific buffer or string
(tp-set START END '(PROPERTY VALUE ...) OBJECT)
;; Entire string (flat properties)
(tp-set STRING PROPERTY VALUE ...)
Examples:
;; Set face on buffer region
(tp-set 1 10 '(face bold)) ; => (1 . 10)
;; Set multiple properties
(tp-set 1 10 '(face bold help-echo "Click me"))
;; Set on specific buffer
(tp-set 1 10 '(face italic) my-buffer)
;; Set properties on a string (0-indexed)
(setq my-string (tp-set 0 5 '(face italic) "Hello World"))
;; => #("Hello World" 0 5 (face italic))
;; Set properties on entire string
(tp-set "Hello" 'face 'bold 'mouse-face 'highlight)
;; => #("Hello" 0 5 (face bold mouse-face highlight))
tp-reset - Replace All Properties
Completely replace ALL text properties with the specified ones.
(tp-reset START END '(PROPERTY VALUE ...) &optional OBJECT)
(tp-reset STRING PROPERTY VALUE ...)
Examples:
;; Replace all properties in region
(tp-reset 1 10 '(face bold)) ; Any existing properties are removed
;; On string
(tp-reset "Hello" 'face 'italic)
tp-add - Add/Merge Properties
Add or update properties with deep merge support for nested plists.
(tp-add START END '(PROPERTY VALUE ...) &optional OBJECT)
(tp-add STRING PROPERTY VALUE ...)
Examples:
;; Add properties (preserves existing, merges nested)
(tp-add 1 10 '(help-echo "tooltip"))
;; Deep merge face properties
(tp-set 1 10 '(face (:foreground "red")))
(tp-add 1 10 '(face (:background "blue")))
;; Result: face is (:foreground "red" :background "blue")
;; Face prepending - symbol faces are prepended to face list
(tp-set "Hello" 'face 'bold)
(tp-add "Hello" 'face 'shadow)
;; Result: face is (shadow bold)
tp-get - Get Property Value
Get property value(s) from range or string, with support for nested sub-properties.
Returns a list of (START END VALUE) intervals, allowing you to see all property values across the range.
For single position queries, use tp-at instead.
;; Range - specific property (returns list of intervals)
(tp-get START END PROPERTY)
(tp-get START END PROPERTY OBJECT)
;; Range with property path as list
(tp-get START END '(PROPERTY) OBJECT)
(tp-get START END '(PROPERTY SUB-KEY ...) OBJECT)
;; Range with deeply nested property path
(tp-get START END '(PROPERTY SUB-KEY SUB-SUB-KEY ...) OBJECT)
;; Range extracting multiple keys from nested property
(tp-get START END '(PROPERTY SUB-KEY (KEY1 KEY2 ...)) OBJECT)
;; Range - all properties (returns list of intervals)
(tp-get START END)
(tp-get START END OBJECT)
;; Entire string (returns list of intervals)
(tp-get STRING)
(tp-get STRING PROPERTY)
(tp-get STRING PROPERTY SUB-KEY ...)
(tp-get STRING PROPERTY SUB-KEY '(KEY1 KEY2 ...))
(tp-get STRING '(PROPERTY SUB-KEY ...))
Examples:
;; Get from range - returns list of (START END VALUE) intervals
(tp-get 1 10 'face) ; => ((1 6 bold))
;; Get with multiple intervals
(setq str (copy-sequence "Hello World Hello"))
(tp-set 0 5 '(face bold) str)
(tp-set 12 17 '(face italic) str)
(tp-get 0 17 'face str) ; => ((0 5 bold) (12 17 italic))
;; Get with property path as list
(setq my-string (copy-sequence "Hello World Hello World"))
(put-text-property 5 20 'face '(:underline (:style wave)) my-string)
(tp-get 5 20 '(face :underline :style) my-string) ; => ((5 20 wave))
;; Get deeply nested property from entire string
(setq str (copy-sequence "Hello World"))
(put-text-property 0 5 'face '(:underline (:color "green")) str)
(put-text-property 6 11 'face '(:underline (:color "yellow")) str)
(tp-get str 'face :underline :color) ; => ((0 5 "green") (6 11 "yellow"))
;; Get multiple keys from nested property
(setq str (copy-sequence "Hello World"))
(put-text-property 0 5 'face '(:underline (:color "green" :style wave)) str)
(put-text-property 6 11 'face '(:underline (:color "yellow" :style line)) str)
(tp-get str 'face :underline '(:color :style))
;; => ((0 5 (:color "green" :style wave)) (6 11 (:color "yellow" :style line)))
;; Get all properties from range
(tp-get 1 10) ; => ((1 6 (face bold help-echo "test")))
;; Get from entire string - returns list of intervals
(setq str (copy-sequence "Hello World Hello"))
(tp-set 0 5 '(face bold) str)
(tp-set 12 17 '(face italic) str)
(tp-get str) ; => ((0 5 (face bold)) (12 17 (face italic)))
(tp-get str 'face) ; => ((0 5 bold) (12 17 italic))
tp-at - Get Property at Position
;; Get all properties at position
(tp-at POS)
(tp-at POS OBJECT)
;; Get specific property at position
(tp-at POS PROPERTY)
(tp-at POS PROPERTY OBJECT)
;; Get nested sub-property at position
(tp-at POS '(PROPERTY SUB-KEY ...))
(tp-at POS '(PROPERTY SUB-KEY ...) OBJECT)
Get text properties at POS, optionally filtered by PROPERTY.
For single-position property queries (previously done with tp-get), use tp-at.
Examples:
;; Get all properties at position 5 in current buffer
(tp-at 5) ; => (face bold help-echo "test")
;; Get all properties at position 0 in string
(setq my-string (tp-set "Hello" 'face 'italic 'help-echo "greeting"))
(tp-at 0 my-string) ; => (face italic help-echo "greeting")
;; Get specific property at position
(tp-at 5 'face) ; => bold
(tp-at 0 'face my-string) ; => italic
;; Get nested sub-property at position
(tp-at 5 '(face :foreground)) ; => "red"
(tp-at 5 '(face :box :color)) ; => "blue"
(tp-at 5 '(display :width)) ; => 10
;; Get nested sub-property from string
(setq str (copy-sequence "Hello"))
(put-text-property 0 5 'face '(:foreground "red" :underline t) str)
(tp-at 0 '(face :foreground) str) ; => "red"
tp-remove - Remove Property
Remove a property or nested sub-property from a region or entire string.
;; Remove entire property (buffer)
(tp-remove START END PROPERTY &optional OBJECT)
;; Remove sub-property (buffer)
(tp-remove START END '(PROPERTY SUB-KEY) &optional OBJECT)
;; Remove nested sub-properties (buffer)
(tp-remove START END '(PROPERTY SUB-KEY (NESTED-KEYS...)) &optional OBJECT)
;; Remove from entire string
(tp-remove STRING PROP1 PROP2 ...)
(tp-remove STRING PROPERTY SUB-KEY)
(tp-remove STRING PROPERTY SUB-KEY '(NESTED-KEYS...))
Examples:
;; Remove entire property
(tp-remove 1 10 'face)
;; Remove sub-property from face
(tp-remove 1 10 '(face :underline))
;; Remove specific nested keys, keep others
(tp-remove 1 10 '(face :underline (:style :position)))
;; Removes :style and :position from :underline
;; If :color exists in :underline, it's preserved
;; Remove from entire string
(tp-remove "Hello World" 'face 'help-echo) ; Remove multiple properties
(tp-remove "Hello World" 'face :underline) ; Remove sub-property
(tp-remove "Hello World" 'face :underline '(:style :position)) ; Remove nested
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
Pattern Matching Functions
tp-match-set - Match String
(tp-match-set PATTERN PLIST &optional OBJECT)
Set properties on all occurrences of a string pattern.
PATTERN can be a string (single pattern) or a list of strings (multiple patterns).
PLIST is a property list like '(face bold help-echo "tip").
OBJECT is a buffer or string; nil means current buffer.
Examples:
;; In buffer - returns list of (START . END) pairs
(tp-match-set "TODO" '(face warning))
;; => ((10 . 14) (50 . 54) ...)
;; On string - returns modified string
(tp-match-set "o" '(face bold) "Hello World")
;; => #("Hello World" 4 5 (face bold) 7 8 (face bold))
;; Multiple patterns - match both "world" and "Hello"
(tp-match-set '("world" "Hello") '(face bold))
;; Matches all occurrences of "world" AND all occurrences of "Hello"
;; Multiple patterns on string
(tp-match-set '("Hello" "world") '(face bold) "Hello world")
;; => #("Hello world" 0 5 (face bold) 6 11 (face bold))
tp-match-reset - Match and Reset
Reset (completely replace) all properties on matches.
PATTERN can be a string or list of strings (multiple patterns).
PLIST is a property list like '(face bold help-echo "tip").
OBJECT is a buffer or string; nil means current buffer.
(tp-match-reset PATTERN PLIST &optional OBJECT)
Examples:
(tp-match-reset "TODO" '(face warning))
;; Replaces ALL properties on matched text
;; Multiple patterns
(tp-match-reset '("TODO" "FIXME") '(face warning))
;; Replaces properties on all occurrences of "TODO" and "FIXME"
tp-match-add - Match and Add
Add/merge properties on matches with deep merge support.
PATTERN can be a string or list of strings (multiple patterns).
PLIST is a property list like '(face bold help-echo "tip").
OBJECT is a buffer or string; nil means current buffer.
(tp-match-add PATTERN PLIST &optional OBJECT)
Examples:
(tp-match-add "TODO" '(face (:underline t)))
;; Merges with existing properties
;; Multiple patterns
(tp-match-add '("TODO" "FIXME") '(face (:underline t)))
;; Merges properties on all occurrences of "TODO" and "FIXME"
tp-regexp-set - Match Regexp
(tp-regexp-set PATTERN PLIST &optional OBJECT)
Set properties on all matches of a regular expression.
PATTERN can be a string (single regexp) or a list of strings (multiple regexps).
PLIST is a property list like '(face bold help-echo "tip").
OBJECT is a buffer or string; nil means current buffer.
Examples:
;; Highlight all numbers in buffer
(tp-regexp-set "[0-9]+" '(face font-lock-number-face))
;; On string
(tp-regexp-set "[A-Z]+" '(face bold) "Hello WORLD")
;; => #("Hello WORLD" 6 11 (face bold))
;; Multiple regexps - match both numbers and uppercase letters
(tp-regexp-set '("[0-9]+" "[A-Z]+") '(face bold) "abc 123 XYZ")
;; Matches "123" and "XYZ"
tp-regexp-reset - Regexp and Reset
Reset (completely replace) all properties on regexp matches.
PATTERN can be a string or list of strings (multiple regexps).
PLIST is a property list like '(face bold help-echo "tip").
OBJECT is a buffer or string; nil means current buffer.
(tp-regexp-reset PATTERN PLIST &optional OBJECT)
tp-regexp-add - Regexp and Add
Add/merge properties on regexp matches with deep merge support.
PATTERN can be a string or list of strings (multiple regexps).
PLIST is a property list like '(face bold help-echo "tip").
OBJECT is a buffer or string; nil means current buffer.
(tp-regexp-add PATTERN PLIST &optional OBJECT)
Search & Navigation Functions
tp-search-forward / tp-search-backward
(tp-search-forward PROPERTY &optional VALUE PREDICATE NOT-CURRENT)
(tp-search-backward PROPERTY &optional VALUE PREDICATE NOT-CURRENT)
Raw wrappers for Emacs's text-property-search-forward and text-property-search-backward.
These are low-level search functions that work directly with prop-match objects.
tp-forward / tp-backward
(tp-forward PROPERTY &optional VALUE OBJECT N)
(tp-backward PROPERTY &optional VALUE OBJECT N)
Search forward/backward N times for text with PROPERTY.
- N is the number of searches, defaulting to 1.
- VALUE is the optional value to match.
- OBJECT can be a buffer or string; nil defaults to current buffer.
- For buffers, returns the prop-match object from the last successful search.
- For strings, returns a list of (START END VALUE) for all matches found.
Examples:
;; Find next text with 'marker property
(tp-forward 'marker)
;; Find next text where 'type equals 'heading
(tp-forward 'type 'heading)
;; Search forward 3 times
(tp-forward 'marker nil nil 3)
;; Search in a string
(setq my-string (copy-sequence "Hello World Hello"))
(tp-set 0 5 '(marker t) my-string)
(tp-set 12 17 '(marker t) my-string)
(tp-forward 'marker nil my-string 2)
;; => ((0 5 t) (12 17 t))
tp-forward-do / tp-backward-do
(tp-forward-do FUNCTION PROPERTY &optional VALUE OBJECT POINT N)
(tp-backward-do FUNCTION PROPERTY &optional VALUE OBJECT POINT N)
Search forward/backward N times for text with PROPERTY and apply FUNCTION to matched text.
- FUNCTION receives the matched text as its only argument. The return value of FUNCTION replaces the matched text in the string or buffer.
- N is the number of searches, defaulting to 1.
- OBJECT can be a buffer or string; nil defaults to current buffer.
- POINT is the starting position for search; for buffers nil means current point, for strings nil means 0 (forward) or end of string (backward).
- Returns the number of successful matches.
Examples:
;; Upcase matched text in buffer (starting from current point)
(tp-forward-do #'upcase 'marker nil nil nil 3)
;; Upcase matched text in string (starting from position 0)
(setq my-string (copy-sequence "hello world hello"))
(tp-set 0 5 '(marker t) my-string)
(tp-set 12 17 '(marker t) my-string)
(tp-forward-do #'upcase 'marker nil my-string nil 2)
;; my-string is now "HELLO world HELLO"
;; Start search from specific position
(setq my-string (copy-sequence "hello world hello"))
(tp-set 0 5 '(marker t) my-string)
(tp-set 12 17 '(marker t) my-string)
(tp-forward-do #'upcase 'marker nil my-string 6 2)
;; Only matches from position 6 onward are processed
;; my-string is now "hello world HELLO"
;; Custom transformation
(tp-forward-do
(lambda (text)
(concat "[" text "]"))
'marker nil nil nil 3)
tp-search - Search All Matches
;; Buffer/string region
(tp-search START END PROPERTY &optional VALUE OBJECT)
;; Entire string
(tp-search STRING PROPERTY &optional VALUE)
Search for all text with PROPERTY in a buffer/string range or entire string.
Returns a list of (START END VALUE) for all matching regions.
Examples:
;; Find all 'marker properties in buffer range
(tp-search 1 100 'marker)
;; => ((5 10 t) (20 25 t) ...)
;; Find all 'type properties with value 'heading in string
(tp-search my-string 'type 'heading)
;; => ((0 10 heading) (50 60 heading) ...)
;; Filter by value
(tp-search 1 100 'type 'heading)
tp-search-map - Apply Function to Matched Text
;; Buffer/string region
(tp-search-map FUNCTION START END PROPERTY &optional VALUE OBJECT)
;; Entire string
(tp-search-map FUNCTION STRING PROPERTY &optional VALUE)
Apply FUNCTION to matched text for all matches of PROPERTY.
- FUNCTION receives the matched text as its only argument. The return value of FUNCTION replaces the matched text in the string or buffer.
- Returns the number of matches processed.
Examples:
;; Upcase all markers in string
(tp-search-map #'upcase my-string 'marker)
;; Upcase all markers in buffer range
(tp-search-map #'upcase 1 100 'marker)
;; Custom transformation
(tp-search-map
(lambda (text)
(concat "[" text "]"))
my-string 'marker)
The Property Layer System
The property 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.
Property Layer Concept
┌─────────────────────────────┐
│ TOP LAYER (visible) │ ← idx=0, What you see
├─────────────────────────────┤
│ Middle Layer (hidden) │ ← idx=1, Preserved
├─────────────────────────────┤
│ Bottom Layer (hidden) │ ← idx=-1, Preserved
└─────────────────────────────┘
Property Layer Definition
tp-define-layer - Define Layer(s)
Define a single layer or a group of multiple layers.
Single Layer:
(tp-define-layer layer-name
(face (:background "cyan") line-prefix ">>"))
Multiple Layers (Layer Group):
(tp-define-layer my-group
layer-1 ; Reference existing layer
(face (:background "red") line-prefix ">>") ; Anonymous layer
(face (:background "green" :weight bold))) ; Another anonymous layer
The first layer in the definition is the top layer (visible by default).
Examples:
;; Define individual layers
(tp-define-layer highlight
(face (:background "yellow" :foreground "black")))
(tp-define-layer error
(face (:background "red" :foreground "white")
help-echo "Error!"))
(tp-define-layer info
(face (:background "blue" :foreground "white")))
;; Define a layer group
(tp-define-layer status-colors
highlight
error
info)
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.
Property Layer Placement
tp-put-layer - Set Layer at Index
;; Buffer/string region
(tp-put-layer START END LAYER IDX OBJECT)
;; Entire string
(tp-put-layer STRING LAYER IDX)
Set layer(s) at a specific index position in the layer stack.
IDX = 0: Top (visible layer)IDX = -1: Bottom- Other values insert at that position
Examples:
(tp-define-layer base (face default))
(tp-define-layer highlight (face (:background "yellow")))
;; Put base layer at top
(tp-put-layer 1 10 'base 0)
;; Put highlight at index 1 (below top)
(tp-put-layer 1 10 'highlight 1)
;; Put layer at bottom
(tp-put-layer 1 10 'info -1)
tp-push-layer - Push Layer to Top
;; Buffer/string region
(tp-push-layer START END LAYER OBJECT)
;; Entire string
(tp-push-layer STRING LAYER)
Push a layer to the top of the stack (equivalent to tp-put-layer ... 0).
Examples:
(tp-define-layer base (face default))
(tp-define-layer highlight (face (:background "yellow")))
;; Push base layer first
(tp-push-layer 1 10 'base)
;; Push highlight on top (now visible)
(tp-push-layer 1 10 'highlight)
Property Layer Deletion
tp-delete-layer - Delete Layer by Name/Index
;; Buffer/string region
(tp-delete-layer START END LAYER-NAME/IDX OBJECT)
;; Entire string
(tp-delete-layer STRING LAYER-NAME/IDX)
Delete a layer from anywhere in the stack by name or index.
Examples:
;; Remove by name
(tp-delete-layer 1 10 'highlight)
;; Remove top layer (idx=0)
(tp-delete-layer 1 10 0)
;; Remove bottom layer
(tp-delete-layer 1 10 -1)
tp-pop-layer - Pop Top Layer
;; Buffer/string region
(tp-pop-layer START END OBJECT)
;; Entire string
(tp-pop-layer STRING)
Remove the top layer (equivalent to tp-delete-layer ... 0).
Property Layer Movement
tp-raise-layer - Move Layer Up/Down
;; Buffer/string region
(tp-raise-layer START END IDX/LAYER-NAME N OBJECT)
;; Entire string
(tp-raise-layer STRING IDX/LAYER-NAME N)
Raise a layer by N positions. Positive N moves toward top, negative moves toward bottom.
Examples:
;; Move layer1 up by 2 positions
(tp-raise-layer 1 10 'layer1 2)
;; Move layer at idx 2 down by 1 position
(tp-raise-layer 1 10 2 -1)
tp-rotate-layer - Cycle Layers
;; Buffer/string region
(tp-rotate-layer START END OBJECT)
;; Entire string
(tp-rotate-layer STRING)
Rotate layers - top goes to bottom, next becomes visible.
Examples:
;; Stack: highlight (top) -> base (bottom)
(tp-rotate-layer 1 10)
;; Stack: base (top) -> highlight (bottom)
tp-pin-layer - Pin Layer to Top
;; Buffer/string region
(tp-pin-layer START END IDX/LAYER-NAME OBJECT)
;; Entire string
(tp-pin-layer STRING IDX/LAYER-NAME)
Move a specific layer to the top (make it visible).
Examples:
;; Make 'base the top layer
(tp-pin-layer 1 10 'base)
tp-switch-layer - Switch Two Layers
;; Buffer/string region
(tp-switch-layer START END IDX1/NAME1 IDX2/NAME2 OBJECT)
;; Entire string
(tp-switch-layer STRING IDX1/NAME1 IDX2/NAME2)
Swap positions of two layers.
Examples:
;; Switch layer1 and layer2
(tp-switch-layer 1 10 'layer1 'layer2)
Property Layer Merging
tp-merge-layers - Merge Multiple Layers
;; Buffer/string region
(tp-merge-layers START END NEW-LAYER-NAME '(IDX1 LAYER-NAME1 IDX2 ...) OBJECT)
;; Entire string
(tp-merge-layers STRING NEW-LAYER-NAME '(IDX1 LAYER-NAME1 IDX2 ...))
Merge specified layers into a new layer. Earlier layers in the list take precedence.
Examples:
;; Merge layer1 and layer2 into merged-layer
(tp-merge-layers 1 10 'merged-layer '(layer1 layer2))
;; Merge by index
(tp-merge-layers 1 10 'merged '(0 1 2))
tp-flatten-layers - Flatten All Layers
;; Buffer/string region
(tp-flatten-layers START END NAME OBJECT)
;; Entire string
(tp-flatten-layers STRING NAME)
Flatten all layers into a single layer with the given name.
Examples:
;; Flatten all layers into 'flat-layer
(tp-flatten-layers 1 10 'flat-layer)
;; Flatten with nil name (unnamed layer)
(tp-flatten-layers 1 10 nil)
Property 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-define-layer code-base
(face font-lock-keyword-face))
(tp-define-layer code-error
(face (:underline (:color "red" :style wave))
help-echo "Syntax error"))
(tp-define-layer code-debug
(face (:background "dark blue")))
;; Apply base highlighting
(tp-push-layer 1 100 'code-base)
;; Add error highlight on problematic code
(tp-push-layer 50 60 'code-error)
;; Toggle between error and normal view
(defun toggle-error-view ()
(interactive)
(tp-rotate-layer 50 60))
Status Indicator
;; Define status layers as a group
(tp-define-layer status-todo (face (:foreground "gray")))
(tp-define-layer status-progress (face (:foreground "yellow")))
(tp-define-layer status-done (face (:foreground "green")))
(tp-define-layer task-status status-todo status-progress status-done)
;; Cycle through statuses
(defun cycle-task-status ()
(interactive)
(tp-rotate-layer (line-beginning-position) (line-end-position)))
Temporary Highlights
(tp-define-layer temp-highlight
(face (:background "yellow")))
(defun flash-region (start end)
"Flash a region temporarily."
(tp-push-layer start end 'temp-highlight)
(run-with-timer 0.5 nil
(lambda ()
(tp-delete-layer start end 'temp-highlight))))
Aliases
For convenience, tp.el provides these aliases:
| Alias | Original Function |
|---|---|
tp-layer-properties |
tp-layer-props |
tp-layer-group-properties |
tp-group-props |
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