-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathorg-indent-pixel.texi
More file actions
286 lines (204 loc) · 10.4 KB
/
org-indent-pixel.texi
File metadata and controls
286 lines (204 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
\input texinfo @c -*- texinfo -*-
@c %**start of header
@setfilename org-indent-pixel.info
@settitle org-indent-pixel: Pixel-accurate wrap-prefix for variable-pitch Org buffers
@documentencoding UTF-8
@documentlanguage en
@c %**end of header
@dircategory Emacs misc features
@direntry
* Org Indent Pixel: (org-indent-pixel). Pixel-accurate wrap-prefix for variable-pitch Org buffers.
@end direntry
@finalout
@titlepage
@title org-indent-pixel: Pixel-accurate wrap-prefix for variable-pitch Org buffers
@author Pablo Stafforini (@email{pablo@@stafforini.com})
@end titlepage
@contents
@ifnottex
@node Top
@top org-indent-pixel: Pixel-accurate wrap-prefix for variable-pitch Org buffers
This manual describes the features and customization options for the Emacs Lisp file @samp{org-indent-pixel.el}.
@end ifnottex
@menu
* Overview::
* Commands::
* Functions::
* Installation::
* Troubleshooting::
* License::
* Indices::
@detailmenu
--- The Detailed Node Listing ---
Overview
* The problem::
* The fix::
* Compatibility notes::
Commands
* Toggling the mode::
Functions
* Automatic activation::
Installation
* With @code{use-package} and @code{elpaca}::
* With @code{use-package} and @code{package-vc}::
* With @code{use-package} and @code{straight}::
* With @code{use-package} and @code{quelpa}::
* Manual installation::
Troubleshooting
* The mode refuses to activate::
* Indentation looks correct without this package::
* Indentation looks wrong after changing fonts::
Indices
* Function index::
* Variable index::
@end detailmenu
@end menu
@node Overview
@chapter Overview
@samp{org-indent-pixel.el} fixes a visual alignment problem that arises when using variable-pitch fonts in Org mode buffers with indentation enabled. It requires GNU Emacs 29.1 or later and Org 9.6 or later.
The development repository is on @uref{https://github.com/benthamite/org-indent-pixel, GitHub}.
@menu
* The problem::
* The fix::
* Compatibility notes::
@end menu
@node The problem
@section The problem
When @code{org-indent-mode} and @code{buffer-face-mode} (or its alias @code{variable-pitch-mode}) are both active, wrapped lines in nested list items become progressively misaligned. The deeper the nesting, the worse the misalignment:
@example
- Level 1 text that wraps to the next
line aligns correctly (small error)
- Level 2 text that wraps starts to
drift rightward
- Level 3 text wraps even further
off from where it should be
@end example
This happens because @code{org-indent-mode} constructs its @code{wrap-prefix} text property from fixed-width space characters. In a monospaced font every space has the same width, so @emph{N} spaces produce exactly the right indentation. In a variable-pitch font, however, spaces are typically narrower than the average character, so @emph{N} spaces fall short of the intended column. The error is proportional to the indentation depth, which is why deeply nested items look worse.
@node The fix
@section The fix
@code{org-indent-pixel-mode} installs @samp{:after} advice on the internal function @code{org-indent-set-line-properties}. For each non-heading line that carries indentation, the advice:
@enumerate
@item
Extracts the buffer text from the beginning of the line up to the body start column.
@item
Measures the pixel width of that text in the buffer's variable-pitch font, including any display properties set by packages such as @uref{https://github.com/minad/org-modern, org-modern} (e.g., bullet character replacements).
@item
Measures the pixel width of the @code{line-prefix} string.
@item
Replaces the space-based @code{wrap-prefix} with a pixel-accurate specification of the form @code{(space :width (N))}, where @emph{N} is the sum of the two pixel measurements.
@end enumerate
The result is that wrapped continuation lines align exactly with the body text above, regardless of the font in use.
@node Compatibility notes
@section Compatibility notes
The mode requires a graphical display (GUI Emacs). In a terminal, all characters occupy the same width, so the built-in space-based prefix from @code{org-indent-mode} is already correct. If you attempt to enable @code{org-indent-pixel-mode} in a terminal frame, it will refuse to activate and display a message explaining why.
Users of @uref{https://gitlab.com/jabranham/mixed-pitch, mixed-pitch} typically do @strong{not} need this package. @code{mixed-pitch} applies variable-pitch faces to individual text runs while leaving structural elements (such as leading whitespace and indentation) in a fixed-pitch face. Because the indentation area stays monospaced, the space-based prefix from @code{org-indent-mode} remains accurate.
@node Commands
@chapter Commands
@menu
* Toggling the mode::
@end menu
@node Toggling the mode
@section Toggling the mode
@findex org-indent-pixel-mode
The command @code{org-indent-pixel-mode} toggles pixel-accurate wrap-prefix correction in the current buffer. You can invoke it interactively with @samp{M-x org-indent-pixel-mode}.
When the mode is enabled, it installs global advice on @code{org-indent-set-line-properties} and immediately reprocesses all lines in the buffer to apply pixel-accurate wrap-prefix values. When the mode is disabled, it triggers @code{org-indent-mode} to reprocess all lines, restoring the original space-based prefixes.
The advice is reference-counted: it is installed when the first buffer enables the mode and removed only when the last buffer disables it. This ensures that enabling the mode in multiple Org buffers simultaneously works correctly.
In most cases you will not need to toggle the mode manually. Instead, use @code{org-indent-pixel-setup} to have it activated automatically (@ref{Automatic activation}).
@node Functions
@chapter Functions
@menu
* Automatic activation::
@end menu
@node Automatic activation
@section Automatic activation
@findex org-indent-pixel-setup
The function @code{org-indent-pixel-setup} registers hooks so that @code{org-indent-pixel-mode} is enabled automatically in any Org buffer where both @code{org-indent-mode} and @code{buffer-face-mode} are active. Call it once in your init file:
@lisp
(org-indent-pixel-setup)
@end lisp
Internally, it adds a function to @code{org-mode-hook} (at depth 90, so it runs after @code{org-indent-mode} has been set up) and to @code{buffer-face-mode-hook}. The hook function checks whether all three conditions are met---@code{org-mode} derivative, @code{org-indent-mode} active, and @code{buffer-face-mode} active---before enabling the pixel mode. It also deactivates the pixel mode if @code{buffer-face-mode} is subsequently turned off.
On a non-graphical display, @code{org-indent-pixel-setup} does nothing.
@findex org-indent-pixel-teardown
The function @code{org-indent-pixel-teardown} reverses the effect of @code{org-indent-pixel-setup}. It removes both hooks and disables @code{org-indent-pixel-mode} in every buffer where it is currently active. This is useful if you want to unload or disable the package without restarting Emacs.
@node Installation
@chapter Installation
@menu
* With @code{use-package} and @code{elpaca}::
* With @code{use-package} and @code{package-vc}::
* With @code{use-package} and @code{straight}::
* With @code{use-package} and @code{quelpa}::
* Manual installation::
@end menu
@node With @code{use-package} and @code{elpaca}
@section With @code{use-package} and @code{elpaca}
@lisp
(use-package org-indent-pixel
:ensure (:host github :repo "benthamite/org-indent-pixel")
:init
(org-indent-pixel-setup))
@end lisp
@node With @code{use-package} and @code{package-vc}
@section With @code{use-package} and @code{package-vc}
@lisp
(use-package org-indent-pixel
:vc (:url "https://github.com/benthamite/org-indent-pixel")
:init
(org-indent-pixel-setup))
@end lisp
@node With @code{use-package} and @code{straight}
@section With @code{use-package} and @code{straight}
@lisp
(use-package org-indent-pixel
:straight (:host github :repo "benthamite/org-indent-pixel")
:init
(org-indent-pixel-setup))
@end lisp
@node With @code{use-package} and @code{quelpa}
@section With @code{use-package} and @code{quelpa}
@lisp
(use-package org-indent-pixel
:quelpa (org-indent-pixel :fetcher github :repo "benthamite/org-indent-pixel")
:init
(org-indent-pixel-setup))
@end lisp
@node Manual installation
@section Manual installation
Clone the repository and add it to your @code{load-path}:
@lisp
(add-to-list 'load-path "/path/to/org-indent-pixel")
(require 'org-indent-pixel)
(org-indent-pixel-setup)
@end lisp
@node Troubleshooting
@chapter Troubleshooting
@menu
* The mode refuses to activate::
* Indentation looks correct without this package::
* Indentation looks wrong after changing fonts::
@end menu
@node The mode refuses to activate
@section The mode refuses to activate
@code{org-indent-pixel-mode} requires a graphical display. If you see the message ``org-indent-pixel-mode requires a graphical display'', you are running Emacs in a terminal. The mode is not needed in terminal Emacs because all characters have the same width.
If you are using @code{org-indent-pixel-setup} and the mode does not activate despite being in a GUI frame, verify that both @code{org-indent-mode} and @code{buffer-face-mode} are active in the buffer. You can check with @samp{M-x describe-mode} or by evaluating @code{(and org-indent-mode buffer-face-mode)} in the buffer.
@node Indentation looks correct without this package
@section Indentation looks correct without this package
If you use @uref{https://gitlab.com/jabranham/mixed-pitch, mixed-pitch} rather than @code{buffer-face-mode} or @code{variable-pitch-mode}, the indentation area stays in a fixed-pitch face and the built-in space-based prefix is already accurate (@ref{Compatibility notes}). You do not need this package in that case.
@node Indentation looks wrong after changing fonts
@section Indentation looks wrong after changing fonts
If you change your variable-pitch font while @code{org-indent-pixel-mode} is active, the cached pixel measurements from the previous font may be stale. Toggle the mode off and back on, or run @samp{M-x org-indent-pixel-mode} twice, to force a full reprocessing of all lines.
@node License
@chapter License
@samp{org-indent-pixel.el} is free software, distributed under the terms of the @uref{https://www.gnu.org/licenses/gpl-3.0.html, GNU General Public License, version 3} or later.
@node Indices
@chapter Indices
@menu
* Function index::
* Variable index::
@end menu
@node Function index
@section Function index
@printindex fn
@node Variable index
@section Variable index
@printindex vr
@bye