{
"provider_url": "https://scripter.co",
"authors": [
{
"url": null,
"name": "Kaushal Modi"
}
],
"provider_display": "scripter.co",
"related": [],
"favicon_url": "https://scripter.co/favicon-16x16.30da33df67e4ae4a58e94188d1d05862d27dbaaf5d2dd661b3b31810ea0005ee.png",
"keywords": [
{
"score": 0,
"name": "src-block"
},
{
"score": 0,
"name": "org-block"
},
{
"score": 0,
"name": "split"
},
{
"score": 0,
"name": "advice"
},
{
"score": 0,
"name": "emacs"
},
{
"score": 0,
"name": "org"
},
{
"score": 0,
"name": "elisp"
}
],
"app_links": [],
"original_url": "https://scripter.co/splitting-an-org-block-into-two/",
"media": {},
"content": "<div>\n<p>If I have a huge Org Src block, I'd like to split it into multiple Org Src blocks so that I can write my explanations in-between.</p>\n<p>So I'd like to quickly split up:</p>\n<p>into:</p>\n<p>&#9757; <em>Click for animation.</em></p>\n<h2>Action Plan <a href=\"https://scripter.co/splitting-an-org-block-into-two/#action-plan\">#</a>\n</h2>\n<ol>\n\t<li>Write a function to return <em>non-nil</em> if point is in <strong>any</strong> Org block - Not just \"src\", \"example\", \"export\" or any of the inbuilt Org blocks.. but also any Org Special block like<code>#+begin_foo .. #+end_foo</code>.</li>\n\t<li>Write a function that does this imagined block splitting.</li>\n\t<li>Overload the <kbd>M-return</kbd> binding so that this block splitting function gets called only when the point is inside an Org block (detected using that first function).</li>\n</ol> \n<p> Thanks to the comment by reader <strong>Mankoff</strong>, I learnt about the <code>org-babel-demarcate-block</code> function (bound by default to <kbd>C-c C-v d</kbd> and <kbd>C-c C-v C-d</kbd>).</p>\n<p>This function varies from the solution in this post in at least two ways:</p>\n<ol>\n\t<li>It works only for Org Src blocks.</li>\n\t<li>It splits the block exactly at where the point is, whereas I would like to always split only at EOL or BOL.</li>\n</ol> \n<p>But I can see that <code>org-babel-demarcate-block</code> can cover most of the block splitting use cases.</p>\n<h2>Am I in an Org block? <a href=\"https://scripter.co/splitting-an-org-block-into-two/#org-in-any-block-p\">#</a>\n</h2>\n<p>Before venturing into writing this function, I looked at these existing ones, but none did what I exactly wanted:</p>\n<p></p><dt><code>org-in-src-block-p</code></dt><dd>Returns <em>non-nil</em> only if the point is in a<code>#+begin_src .. #+end_src</code> block; not when point is in any other Org block.</dd><dt><code>org-in-block-p</code></dt><dd>Returns <em>non-nil</em> only if the point is in one of the pre-defined block names passed as a list (<code>'(\"src\" \"example\" \"quote\" ..)</code>). So this again won't work as I cannot pre-define all Org Special blocks.</dd> \n<p>So I define the below <code>modi/org-in-any-block-p</code> function that returns <em>non-nil</em> if the point is in-between any <code>#+begin_FOOBAR .. #+end_FOOBAR</code>. Thankfully, I was able to reuse a lot of logic from the <code>org-between-regexps-p</code> function ( <code>org-in-block-p</code> uses that function internally).</p>\n<ul>\n\t<li>\n<code>(case-fold-search t)</code> ensures that either <code>#+BEGIN_ ..</code> or <code>#+begin_ ..</code> match.</li>\n\t<li>The regular expression in <code>block-begin-re</code> matches with<code>\"#+begin_src foo\"</code> or <code>\" #+begin_src foo\"</code> or <code>\"#+BEGIN_EXAMPLE\"</code> or<code>\"#+begin_FOOBAR\"</code> or ..</li>\n\t<li>The <code>limit-up</code> and <code>limit-down</code> are set to the buffer locations of the previous and next Org headings. The following regexp searches are limited to happen in those bounds for better performance.</li>\n\t<li>The <code>block-end-re</code> is dynamically constructed based on the string matched using<code>block-begin-re</code>. This is so that if <code>\"#+begin_quote\"</code> is found initially, it matches the block ending with specifically<code>\"#+end_quote\"</code> and not something like <code>\"#+end_src\"</code>.</li>\n\t<li>\n<em>nil</em> is returned if the point is not between <code>#+begin_FOOBAR .. #+end_FOOBAR</code>.</li>\n</ul>\n<dl>\n<dt>Caveat</dt>\n<dd>I haven't gone extra lengths to support nested block cases, specifically where the point is outside the inner-most block, but still inside the outer block:</dd>\n</dl> <h2>If so, split the block <a href=\"https://scripter.co/splitting-an-org-block-into-two/#org-block-split\">#</a>\n</h2>\n<ol>\n\t<li>\n<p>If the point is anywhere on the line, but not at the beginning of the line (BOL),</p>\n<ul>\n<p>Go to the end of the line, and then split the block.</p>\n<p>So if the point is after the first <code>message</code> identifier, or at the end of that first <code>message</code> line:</p>\n<p>Split the block at the point <strong>after</strong> <code>(message \"one\")</code> and move the point to between the split blocks:</p> \n</ul>\n</li>\n\t<li>\n<p>Otherwise (if point is at BOL),</p>\n<ul>\n<p>Split the block exactly at that point.</p>\n<p>So if the point is at the beginning of the second <code>message</code> line:</p>\n<p>Split the block at the point <strong>before</strong> <code>(message \"two\")</code> and move the point to between the split blocks:</p> \n</ul>\n</li>\n</ol> \n<p>With the \"point in an Org block\" detection working, I now needed the split to happen with these rules:</p>\n<ul>\n\t<li>The regexp for extracting <code>block-start</code> is the same as<code>block-begin-re</code> in <a href=\"https://scripter.co/splitting-an-org-block-into-two/#code-snippet--modi-org-in-any-block-p\">Code Snippet 1</a>, but with different sub-grouping.</li>\n\t<li>The <code>block-end</code> string is derived from sub-group 1 of <code>block-start</code> string - just replacing \"begin_\" with \"end_\".</li>\n\t<li>And then based on if the point was initially at BOL (<code>at-bol</code>), the insertion of newlines and movement of point is done accordingly.</li>\n</ul> \n<p>So here's the code that follows that spec:</p>\n<h2>Now make <kbd>M-return</kbd> do that <a href=\"https://scripter.co/splitting-an-org-block-into-two/#M-return-split-block-dwim\">#</a>\n</h2>\n<p>With these two functions evaluated, <code>M-x modi/org-split-block</code> will work right away.</p>\n<p> But where's the fun in that?<br></p>\n<ul>\n\t<li>By default, <kbd>M-return</kbd> is used to either create new headings, or do other things like insert an item, wrap a region in table, etc. based on the context. See the doc-string of<code>org-meta-return</code> (function bound to this key by default) for more info.</li>\n\t<li>But it doesn't have a context for \"point in an Org block\". So it tries to create a heading when inside a block too, which doesn't make much sense.</li>\n\t<li>So fix that by adding that context.</li>\n</ul> \n<p>I needed to have the Org block splitting happen with an intuitive binding - like <kbd>M-return</kbd>.</p>\n<p>So I <strong>advise</strong> <code>org-meta-return</code> to call <code>modi/org-split-block</code> when the point is inside an Org block.</p>\n<em>You can tweak the precedence of this new context by moving the <code>((modi/org-in-any-block-p) #'modi/org-split-block)</code> form in that<code>cond</code> form.</em> <p>The advising function <code>modi/org-meta-return</code> is the same as the advised function <code>org-meta-return</code> (as of ), except that a new context<code>(modi/org-in-any-block-p)</code> is added.</p>\n<p>Now with the point in <strong>any</strong> Org block, <kbd>M-return</kbd> away!</p>\n<p>Look for the source of <code>modi/org-split-block</code> (and dependent functions) added to<a href=\"https://github.com/kaushalmodi/.emacs.d/blob/master/setup-files/setup-org.el\"><code>setup-org.el</code></a> in my Emacs config.</p>\n</div>",
"entities": [],
"provider_name": "Scripter",
"type": "html",
"description": "I ventured out to start writing about a 100+ line Emacs Lisp snippet in my config, and then I thought - Wouldn&rsquo;t it be nice if I can quickly split out that huge snippet into smaller Org Src blocks? And so this blog post happened.",
"embeds": [],
"images": [
{
"width": 859,
"url": "https://scripter.co/splitting-an-org-block-into-two/org-split-block.png",
"height": 520,
"caption": null,
"colors": [
{
"color": [
39,
39,
39
],
"weight": 0.942626953125
},
{
"color": [
182,
83,
68
],
"weight": 0.03173828125
},
{
"color": [
116,
70,
62
],
"weight": 0.0146484375
},
{
"color": [
130,
143,
142
],
"weight": 0.010986328125
}
],
"entropy": 0.530681249665,
"size": 69082
},
{
"url": "https://scripter.co/images/me--optimized.1cdf3eb11e9bf7be99d0292930537426d0ffff3f03c0a489a4c45034aebbd5be.jpg",
"width": 400,
"height": 400,
"caption": null,
"size": 14014
}
],
"safe": true,
"offset": -14400000,
"cache_age": 86400,
"lead": null,
"language": "en",
"url": "https://scripter.co/splitting-an-org-block-into-two/",
"title": "Splitting an Org block into two",
"favicon_colors": [
{
"color": [
0,
0,
0
],
"weight": 0.000244140625
}
],
"published": 1534974420000
}