{ "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.940673828125 }, { "color": [ 183, 81, 68 ], "weight": 0.030517578125 }, { "color": [ 120, 68, 61 ], "weight": 0.017578125 }, { "color": [ 130, 134, 133 ], "weight": 0.0087890625 }, { "color": [ 145, 209, 222 ], "weight": 0.00244140625 } ], "entropy": 0.575297330799, "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 }