4

Say I have a buffer with code (in this case Python) organized as follows:

.. cell 1 ..
## 
.. cell 2 ..

# this is a comment

### this is also a comment

.. still cell 2 ..

  ##
  .. cell 3 (code that is indented)

The sequence of characters ## is meant to delimit cells (code regions/blocks) in the buffer. The caracter # starts a comment in Python, so ## is treated as a comment by the language. Similar constructions could be built in e.g. Elisp with ;; or other programming languages.

I would like to define an Emacs command that when invoked, it defines the current cell (i.e. the cell on which point/cursor currently sits.) to be the Emacs region (i.e. it highlights the cell).

How can I do this in Emacs?

For reference:

  • The is akin to the notion of cells or code sections in MATLAB
  • Here is a thread for implementing this functionality in Vim.
Community
  • 1
  • 1
Josh
  • 11,979
  • 17
  • 60
  • 96

3 Answers3

3

Here's a solution:

(defun python-inside-comment-p ()
  (save-excursion
    (beginning-of-line 1)
    (looking-at "^#")))

(defun python-select-cell ()
  (interactive)
  (goto-char
   (if (re-search-backward "^\\s-*##[^#]" nil t)
       (match-end 0)
     (point-min)))
  (while (and (python-inside-comment-p)
              (eq 0 (forward-line 1)))
    nil)
  (set-mark (point))
  (goto-char
   (if (re-search-forward "^\\s-*\\(##[^#]\\)" nil t)
       (- (match-beginning 1) 2)
     (point-max))))

Tested with:

print "Beautiful is better than ugly."
##
print "Explicit is better than implicit."
print "Simple is better than complex."
print "Complex is better than complicated."
# this is a comment
print "Flat is better than nested."
### this is also a comment
print "Sparse is better than dense."
##
print "Readability counts."
print "Special cases aren't special enough to break the rules."
print "Although practicality beats purity."
print "Errors should never pass silently."
print "Unless explicitly silenced."

Works OK. Is there a reason not to use indentation levels rather than comments as anchors?

abo-abo
  • 20,038
  • 3
  • 50
  • 71
  • Thanks. Would you mind elaborating on the difference between this approach and that of @legoscia? – Josh Oct 18 '13 at 16:18
  • 1
    Mine skips comments. Otherwise they're same. – abo-abo Oct 18 '13 at 16:24
  • Thanks - I am having problems making it work when `##` is indented. Any thoughts on how to fix it? (I updated the last cell in the OP to show this) – Josh Oct 18 '13 at 16:28
2

That would be something like this:

(defun mark-cell ()
  (interactive)
  (search-backward-regexp "^##\\($\\|[^#]\\)" nil 'noerror)
  (push-mark)
  (end-of-line)
  (search-forward-regexp "^##\\($\\|[^#]\\)" nil 'noerror)
  (beginning-of-line)
  (activate-mark))

For me, it doesn't highlight the cell (you can do that manually with C-x C-x), even though that is what activate-mark should do, if I understand correctly.

legoscia
  • 39,593
  • 22
  • 116
  • 167
1

From EmacsWiki, there are two packages:

python-x also provides some additional features

python-cell provides Matlab-like cells in python buffers