85 lines
3.5 KiB
Plaintext
85 lines
3.5 KiB
Plaintext
|
||
|
||
<p>Earlier today I wanted to convert a bunch of Org meta data keywords to
|
||
lower case notation, with the help of <code>isearch-forward-regexp</code> and
|
||
<code>query-replace-regexp</code>. This included everything from special comments,
|
||
like <code>#+TITLE:</code> to property drawers in the form of <code>:PROPERTIES:</code>.
|
||
There were 340 such cases in my file and I was reluctant to do so
|
||
manually. Thankfully, Emacs makes such a task fairly simple once you
|
||
get past the essentials, because it lets you evaluate arbitrary Elisp
|
||
forms for the replacement text. This includes the possibility of
|
||
running some function on a matched regexp group. In this case that
|
||
function was <code>(downcase OBJECT)</code>.</p>
|
||
|
||
<p>First I needed a regular expression that would capture all targets.
|
||
<code>isearch-forward-regexp</code> and its <code>query-replace-regexp</code> counterpart
|
||
expect a single backslash for the escape character, so I ended up with
|
||
this pattern:</p>
|
||
|
||
<pre><code>^\(#\|:\)[^ ].*?:
|
||
</code></pre>
|
||
|
||
<p>If I were to test this in the buffer, I could use <code>M-x re-builder</code>,
|
||
which however requires double backslashes (same for when you write Elisp
|
||
code):</p>
|
||
|
||
<pre><code>^\\(#\\|:\\)[^ ].*?:
|
||
</code></pre>
|
||
|
||
<ul>
|
||
<li>
|
||
<p>Once I was sure of the regular expression I had to use, I went to the
|
||
top of the buffer and invoked <code>isearch-forward-regexp</code> (bound to
|
||
<code>C-M-s</code> by default).</p>
|
||
</li>
|
||
<li>
|
||
<p>Entered the pattern <code>^\(#\|:\)[^ ].*?:</code>, got live feedback of the
|
||
matching items, and switched to <code>query-replace</code> with <code>C-%</code>
|
||
(<code>isearch-query-replace</code>). When the Isearch is regexp-aware so is the
|
||
corresponding <code>query-replace</code>.</p>
|
||
</li>
|
||
<li>
|
||
<p>For the replacement text I instructed the command to evaluate the
|
||
<code>downcase</code> function. This is done by escaping the comma operator
|
||
(<code>,</code>) and then supplying the function with a regexp group. Because I
|
||
wished to match everything, the group should be <code>\0</code>. Which means
|
||
that the replacement should be expressed thus: <code>\,(downcase \0)</code>.</p>
|
||
</li>
|
||
</ul>
|
||
|
||
<p>Try this with any string in a buffer, say, <code>Hello</code>:</p>
|
||
|
||
<ul>
|
||
<li><code>M-x query-replace-regexp</code></li>
|
||
<li><code>Hello</code></li>
|
||
<li><code>\,(upcase \0)</code></li>
|
||
</ul>
|
||
|
||
<p>Confirm the operation and you should get <code>HELLO</code>. This works with
|
||
multiple groups and can read a series of Elisp forms. An example with
|
||
<code>Hello world</code>:</p>
|
||
|
||
<ul>
|
||
<li><code>M-x query-replace-regexp</code></li>
|
||
<li><code>\(Hello\) \(world\)</code></li>
|
||
<li><code>\,(downcase \1) \,(capitalize \2)</code></li>
|
||
</ul>
|
||
|
||
<p>Which should give you <code>hello World</code>.</p>
|
||
|
||
<p>The elegant minimalism of the <code>query-replace</code> interface grants you the
|
||
power to either replace each match one at a time or hit the exclamation
|
||
mark (<code>!</code>) to answer “yes to all”. This is what I did to downcase all
|
||
340 matches. Voila! All of my Org file’s meta data were converted to
|
||
lower case in one go.</p>
|
||
|
||
<p>Finally, I discovered <code>query-replace-regexp-eval</code> which saves you from
|
||
adding the escaped comma operator for the replacement’s Elisp form.
|
||
However its doc string reads thus:</p>
|
||
|
||
<pre><code>Interactive use of this function is deprecated in favor of the
|
||
‘\,’ feature of ‘query-replace-regexp’. For non-interactive use, a loop
|
||
using ‘search-forward-regexp’ and ‘replace-match’ is preferred.
|
||
</code></pre>
|
||
|
||
|