reddit / emacs
Where Sublime text has the edge over Emacs
cute-pengui · 2022-05-01 19:24
I have found one major limitation in Emacs that I cannot circumvent. Its ability to **expand text** is limited. `abbrev-mode` can expand words into other words or phrases. For example, I can ask Emacs to expand "edv" into "Emacs Developmental Version." However, it can only expand single words, not phrases. For example, it does not appear to be able to expand "Emacs Developmental Version" into "edv". (Or change a phrase like "a lot of" into "many". However, in Sublime Text, one can expand phrases into words and other phrases, using the snippet feature. One can also expand whole sentences. The popular plugin `yasnippet` does not overcome this limitation.
I have been asked to edit a massive collection of classical writings, modernize them, and update the language and grammar. I have a very strict template I have to follow, which means that I have to remove many redundant words, phrases, and even sentences. Much of the process is mechanical, but not all of it is, and so I have to make specific judgements about how the text should read. I mostly use Emacs but could not make it work for me in this use case, although I am now also missing many of its other features.
wargxs · 2022-05-01 19:46
Interesting. But why would you want to do that? Can you give an example use case?
LordAlveric · 2022-05-01 19:59
Not sure how useful a feature like this would be, but you should be able to write a plugin to do what you want, if one is not already in Melpa.
I have Emacs changing the backslash into a delta when I write Haskell. Kinda nice.
[deleted] · 2022-05-01 20:07
[deleted]
XCapitan_1 · 2022-05-01 20:46
Yeah, it sounds quite possible trivial to implement. And porting something *from* Emacs to Sublime may just not be feasible if Sublime doesn't provide the required points of extension :)
I think the only thing where Sublime can be said to have an edge is this fancy minimap, which must've been ported from there to every GUI editor in existence except Emacs... yet.
ieure · 2022-05-01 21:29
You could make this work with yasnippet, by writing a trigger that's more tolerant of whitespace.
I really don't understand your usecase, though. The point of snippets/abbrevs is to *reduce* typing, by expanding a small text into a large one. Building a complex system which replaces "a lot of" (7 chars) with "many" (4 chars) is the opposite of that. Why not type "many" in the first place?
If this is a stylistic thing, you could create a minor mode that highlights phrases like "a lot of" and lets the user *choose* whether to replace it or not.
00-11 · 2022-05-01 21:46
I do ***not*** suggest this as anything like the way to go, but just to show that you can cobble something together in a second or two. This just abuses existing option `directory-abbrev-alist` in the wrong direction.
Select the text `Emacs Developmental Version` and use command `foo`.
Emacs Developmental Version
(setq directory-abbrev-alist '(("\\`Emacs Developmental Version" . "edv")))
(defun foo (beg end)
(interactive "r")
(let ((new (abbreviate-file-name (buffer-substring beg end))))
(delete-region beg end)
(insert new)))
Again, apologies for the misbegotten offer. No one should even *think* of providing what you request this way. `directory-abbrev-alist` is just the only existing such thing I could think of that (without actually wanting to) provides for such backward "expansion" out of the box (and only for directory names, in principle).
----
More to the point: As others have asked, why do you want to do this? Why do consider this an *"edge"* (let alone *"the edge"*) that Emacs is missing?
wargxs · 2022-05-01 21:50
https://github.com/dengste/minimap :-D
dpoggio · 2022-05-01 22:38
Why do you call this a “major” limitation? Writing a replacement tool like this is a trivial exercise. Keep some alist with text and replacements and use a trigger to perform backward search and replace. That’s it.
mee8Ti6Eit · 2022-05-02 00:38
Firstly, why do you want to expand more text into less text? The point is to reduce typing.
Second, since it's Emacs, it's easy to add this feature yourself.
Third, the abbrev feature allows using functions for expansion, and you can easily use an expansion function that checks the last X words for a phrase to expand or shrink.
SickMoonDoe · 2022-05-02 04:41
This sounds like you want basic regex replacement, but don't want to write the 20ish line snippet to make it a convenient keymap.
This doesn't need a plugin, and isn't a "missing feature". Just make a list of replacement pairs, put it in a loop, map it to a key.
ndamee · 2022-05-02 05:07
As others here I also don't get what you want. You want to type "Emacs Developmental Version" to get "edv"? This doesn't really make sense.
Or do you want to replace "Emacs Developmental Version" in an existing text to "edv"? That's replacing text, not abbreviation.
You should give a concrete use case of what you want to achieve, because abbrev does not really make sense with the example you gave.
cute-pengui · 2022-05-02 06:46
Thanks for all your responses. Please see the link below for a use case.
[https://youtu.be/NxfWaIlUj30](https://youtu.be/NxfWaIlUj30)
cute-pengui · 2022-05-02 06:46
>Not sure how useful a feature like this would be
Please see my use case. This is a very useful feature for what I am doing.
cute-pengui · 2022-05-02 06:48
You are right if you are the writer, but not if you are the editor. See my use case.
cute-pengui · 2022-05-02 06:48
I have furnished one above.
cute-pengui · 2022-05-02 06:48
Please show me how.
cute-pengui · 2022-05-02 06:49
Thank you. I am going to test your solution and revert. Please see my use case above.
cute-pengui · 2022-05-02 06:49
Please show me how.
cute-pengui · 2022-05-02 06:50
Please see my use-case above.
nu0or · 2022-05-02 07:26
you seem to use emacs like your ordinary stupid editor (like sublime). emacs is not used like that. learn about elisp and you will implement such trivial stuff in 5 minutes.
SickMoonDoe · 2022-05-02 07:39
This is your bread and butter replacement command for interactive editing.
https://www.gnu.org/software/emacs/manual/html_node/emacs/Unconditional-Replace.html
Abbreviation expansion might also be useful for you https://www.gnu.org/software/emacs/manual/html_node/emacs/Expanding-Abbrevs.html
To make a command that searches and replaces in your file "programmatically", which you would want to use for a keybind:
```
(let ((case-fold-search nil))
(goto-char (point-min))
(while (search-forward "myStr1" nil t)
(replace-match "myReplaceStr1"))
(goto-char (point-min))
(while (search-forward "myStr2" nil t)
(replace-match "myReplaceStr2"))
;; repeat for other string pairs
)
```
cute-pengui · 2022-05-02 09:55
Thank you. I will test this out and revert.
[deleted] · 2022-05-02 09:56
[deleted]
dixius99 · 2022-05-02 10:23
The one that comes to mind for me is for fixing typos like "mean time" into "meantime".
If expanding multiple words to a single word could work, maybe expanding multiple words to multiple words could also work, so typos like "all intent sand purposes" could expand to "all intents and purposes".
XCapitan_1 · 2022-05-02 10:49
I mean, there are a bunch of clones, but none is as usable as the original.
It's not critical though, given that Emacs is primarily a keyboard-driven program.
Phil-Hudson · 2022-05-02 11:58
The newbie asks "Why can't Emacs do x?"
The monthling asks "Can Emacs do x?"
The yearling asks "How many ways can Emacs do x?"
The sage asks "Which of the ways Emacs can do x is best suited for my use case?"
ndamee · 2022-05-02 14:25
Do you have a static list of replacements? If so I created an interactive function for you to do interactive replacements. It has replacement pairs which you can add to the code by following the example of ("replacethat" . "tothat").
You can put this function into emacs, so you can call it with M-x my-replacements. In order to that, copy the function into a file like myreplacements.el and call M-x eval-buffer there to get this new command. You have to do M-x eval-buffer there every time you add new replacement pairs to update the command with more replacements.
(defun my-replacements ()
(interactive)
(let ((replacements '(("replacethis" . "tothis")
("replacethat" . "tothat")
)))
(dolist (replacement replacements)
(goto-char (point-min))
(query-replace (car replacement) (cdr replacement)))))
cute-pengui · 2022-05-02 14:36
I do have many static replacements. This will be a great help. Thank you so much.
cute-pengui · 2022-05-02 14:37
Longing to be a sage Phil, but realizing the hard reality that it may never happen!
ieure · 2022-05-02 15:35
That makes even less sense to me. If an editor is reading someone else's text which already says "a lot of," why would they type that to change it to "many?"
Sounds more like you need a canned list of regexps and replacements.
flylikeabanana · 2022-05-02 15:37
With that attitude it probably wont!
flylikeabanana · 2022-05-02 16:37
Cunningham's law for emacs: to get an emacs question answered, don't ask the question, say that emacs can't do it
Phil-Hudson · 2022-05-02 16:44
Old, dried-out, forgotten, on the shelf... it's not so great.
cute-pengui · 2022-05-02 16:45
That is just an example. I am sorry you could not understand what I am trying to do.
cute-pengui · 2022-05-02 16:46
I am not sure I follow.
Phil-Hudson · 2022-05-02 16:47
It's a pun on "sage" -- old wise one/aromatic herb.
ieure · 2022-05-02 16:53
I understand *what*, I don't understand *why*.
cute-pengui · 2022-05-02 16:59
I have been asked to edit a massive collection of classical writings, modernize them, and update the language and grammar. I have a very strict template I have to follow, which means that I have to remove many redundant words, phrases, and even sentences. Much of the process is mechanical, but not all of it is, and so I have to make specific judgements about how the text should read. I mostly use Emacs but could not make it work for me in this use case, although I am now also missing many of its other features.
cute-pengui · 2022-05-02 16:59
You have it!
WaitingToBeTriggered · 2022-05-02 16:59
HOLD YOUR GROUND
nnreddit-user · 2022-05-02 17:09
Emacs can't impress my crush.
nnreddit-user · 2022-05-02 17:12
Emacs can't make a living wage.
zetaomegagon · 2022-05-03 00:29
You should probably edit this into your og post to avoid more confusion.
[deleted] · 2022-05-03 00:45
[deleted]
zetaomegagon · 2022-05-03 00:45
Lol
dpoggio · 2022-05-03 01:00
Okay, let's assume you are writing this as a module called MS, which stands for "more snippets" and looks redmondish evil. Following conventions, internal lisp functions are prefixed `ms--`. For didactic purposes mostly, I will define a function to show this to you:
`(defun ms--getkeys ($list)`
`"Gets a list of keys from an alist"`
`(mapcar 'car $list))`
This function just applies `mapcar`. So the substitutions will be loaded to an alist, let it be in the spirit of the FIFA World Cup:
`(setq ms-list '(`
`("an italian summer" . "un'estate italiana" )`
`("magic nights" . "notti magiche" )))`
You could change this later to anything. Just... I would not put this as a `defcustom`. Now, as you may understand, there is a list of two pairs of phrases, each pair both in English and Italian. Now you need a function to: search each English phrase backward (from where the point is sitting), get the Italian version of any match, delete the English version and insert the Italian.I will do this using a macro called `dolist`, and a `let` environment, which is like a box where some variables are defined. In this environment, I will define `key` and `val`, corresponding to the found key and its associated value. There is an `and` expression too, which is almost the same as an `if` expression with no ELSE. Finally, you will see `looking-back`, which is like a question: does this string or regexp match what's behind?
`(defun ms-replace-snippet ()`
`"Replaces a string with it's replacement in 'ms-list'"`
`(interactive)`
`(dolist (ms-key (ms--getkeys ms-list))`
`(and (looking-back ms-key)`
`(let ((key ms-key)`
`(val (cdr (assoc ms-key ms-list))))`
`(backward-delete-char-untabify (string-width key) nil)`
`(insert val)))))`
This `let` environment is not necessary, but I wanted you to learn some of the most important tools in elisp. Without the let environment, I would've needed to use a `progn` to keep just one expression after the lookup in the `and` expression:
`(defun ms-replace-snippet ()`
`"Replaces a string with it's replacement in 'ms-list'"`
`(interactive)`
`(dolist (ms-key (ms--getkeys ms-list))`
`(and (looking-back ms-key)`
`(progn`
`(backward-delete-char-untabify (string-width ms-key) nil)`
`(insert (cdr (assoc ms-key ms-list)))))))`
Now, this function is enough to do all the work. If you are standing after "an italian summer", and you use `ms-replace-snippet`, you will get the phrase replaced by "un'estate italiana". Now you can bind this function to a key. If you want, you may even transform this into a pretty basic minor mode, so you can enable and disable it. I don't want to write more now, but there is a simple tutorial [here](https://nullprogram.com/blog/2013/02/06/) (although I dislike his way of defining the keymap and I really recommend adding an alias for it). You can also add a reload function to re-read your sources and populate your alist when the mode is loaded. It's not hard.
**Now, the most important part**: You take my code, copy-paste it, but take a minute to inspect it. You can, in Emacs, sit on each function inside the source and use `C-h f` to learn about it. Do it with `dolist` ;). Do it more. Get used to it. Learning how to use elisp is not hard, and most of the help comes from inside Emacs. You can also use `C-h k` to learn how a specific key or keychord works. I used it to reach `backward-delete-char-untabify` (called by backspace -DEL-). Also, you can have a look at [https://www.gnu.org/software/emacs/manual/](https://www.gnu.org/software/emacs/manual/).
cute-pengui · 2022-05-03 05:17
Thank you very much for this detailed response. I am keen to test this out and will do so and revert to you.
cute-pengui · 2022-05-03 16:04
This does just what I need. Works flawlessly. Thank you!
cute-pengui · 2022-05-03 16:18
Solution works great! Many thanks.
cute-pengui · 2022-05-03 16:18
Solution works great! Many thanks.
cute-pengui · 2022-05-03 16:18
Solution works great! Many thanks.
dpoggio · 2022-05-03 21:49
Sure, glad to help. Play building a minor mode upon this. It’s fun, and you’ll be able to load/unload this functionality every time you want.
cute-pengui · 2022-05-05 03:52
Great idea. Will do.
wargxs · 2022-05-19 11:54
When I first saw these minimaps I thought they would be super useful … but once you learn about marks and pop mark in emacs you realise that they are completely useless and only steal screen estate :)
XCapitan_1 · 2022-05-19 15:01
They are useful for a more mouse-driven navigation. Like, you scroll though the file with the minimap, then do Shift-Click to go to definition, and so on. In programs like Emacs it's indeed out of place.
Also, I use code folding a lot, which I think accomplishes something similar to minimaps.