1

I am trying to customize Emacs by adding a feature where I can select a block of text (like the region but not bound by mark and point).

Currently I have implemented this by setting two variables that mark the start and end of the block.

(defvar block-mark-start nil "Start of block.")
(defvar block-mark-end   nil "End of block.")

This works, I am able to manipulate the text within this block like I want to. However, I am now trying to get the block to be highlighted.

At first I tried manually setting the face of this text:

(add-text-properties block-mark-start block-mark-end '(font-lock-face myface))

This worked, however I was unable to unset the highlighting, this approach also seemed to occasionally break with things not getting highlighted, things outside the block getting highlighted, etc..

So I moved on to trying libraries like Highlight but there doesn't seem to be a way to highlight arbitrary text, you can only use the mouse, region, or regexs. I have similar issues with the secondary selection.

I am trying to emulate the way blocks work in Wordstar / Joe's Own Editor.

2
  • I don't understand your last paragraph. Could you perhaps rephrase it, to state clearly what you haven't found possible with library Highlight? That library doesn't require that you use the region or the mouse to highlight text.
    – Drew
    Apr 13, 2020 at 5:28
  • Instead of asking about your attempted solution (code), please consider asking about what you want to do. What text do you want to highlight (without using the region or a mouse)?
    – Drew
    Apr 13, 2020 at 5:30

2 Answers 2

2

You can use an overlay. An overlay is a thing you can put over text, and it changes properties of that text. You don't want to use too many of these, as apparently there are performance issues with having too many of them. But if you only have a few, this should be fine.

The benefit of using an overlay is that it's simple to undo the text manipulation by moving the overlay to an inconspicuous place (say, from character 0 to 0).

Here is some code that creates an overlay, then moves it over some text:

(defvar zck/overlay
  (let ((overlay (make-overlay 0 0)))
    (overlay-put overlay 'face '((t (:background "#80ffb0"))))
    overlay)
  "We can put this overlay over some text")

(let ((start 5)
      (end 15))
  (move-overlay zck/overlay start end))

The result looks like this:

Example code for creating an overlay, with the overlay over some text.

Note that overlays are specific to the buffer they're created in. So if you create it in one buffer, you have to explicitly move it to a different one.

1

You say that with library Highlight "there doesn't seem to be a way to highlight arbitrary text, you can only use the mouse, region, or regexs. I have similar issues with the secondary selection."

You don't say what your "similar issues" are with the secondary selection, so I can't speak to that.

But in any case, what you say about library Highlight is not true.

You can highlight any bits of text in any buffer using library Highlight. And you can do so using either overlay properties (typically face) or text properties (typically face).

I'm guessing that you're seeing the word "region" in some command names or descriptions and thinking that you need to activate the region to be able to highlight some stretch of text. That's not true.

Here's the point: You need to somehow specify which text you want to highlight.

That means specifying, somehow, its start and end positions in the buffer. You need not do that by having an active region with point and mark at those positions.

For example, command hlt-highlight-property-with-value highlights text that has a given (overlay or text) property with certain values. You don't need to know the start and end for each bit of such text; you need only provide the property and its values. In this case, you are specifying the start and end positions indirectly, by providing the property to look for.

As another example, command hlt-highlight-regexp-region highlights bits of text that match a regexp. It searches for matches, and uses the start and end of each match as the highlighting limits for that bit of text.

Perhaps your confusion results from the fact that some mentions of "region" in the library refer to the scope of the action of a function, and not to a piece of text to highlight. Such functions act on particular bits of text either (1) throughout the entire buffer or (2) throughout the active region. That says nothing about which bits of text to highlight, within either of those scopes. That latter information also needs to be provided to the functions, somehow (see above).

But other functions highlight only a single bit of text. And some of them have region in their name. Why? Because interactively the easiest way to provide two buffer positions to a command is using the active region.

Perhaps the most basic function for highlighting is hlt-highlight-region. Yes, it's a command, which means you can bind it to a key and use it interactively. In that case, the start and end positions of the text to be highlighted are the limits of the active region, or the whole buffer if the region is not active.

But, as C-h f hlt-highlight-region tells you, these are the parameters of that function. The first two specify the limits of the text to highlight.

(hlt-highlight-region &optional START END FACE MSGP MOUSEP BUFFERS)

Optional args START and END are the limits of the area to act on. They default to the region limits. If the region is not active or it is empty, then use the whole buffer. (But see BUFFERS, below.)

Optional 3rd arg FACE is the face to use. Interactively, this is the last face that was used for highlighting. (You can use command hlt-choose-default-face to choose a different face.)

Optional 4th arg MSGP non-nil means to display a progress message. Interactively, MSGP is t.

Optional 5th arg MOUSEP non-nil means use mouse-face, not face. Interactively, MOUSEP is provided by the prefix arg.

Optional 6th arg BUFFERS is the list of buffers to highlight. If non-nil and this command is called interactively then explicit START and END values are ignored, and the actual values are determined automatically for each buffer, based on whether the region is active there.

So the answer to your question is that you need only provide a START and END position to hlt-highlight-region, to highlight the buffer text from START to END. For example, (hlt-highlight-region 100 250 'highlight) highlights the text from buffer position (character) 100 to position 250 using face highlight.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.