Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

help with what should have been a very simple defun

39 views
Skip to first unread message

Btraven

unread,
Jan 17, 2022, 12:45:05 PM1/17/22
to
Dear Emacs gurus:

I have been able to use the following elisp code to number paragraphs in a plain text file but for some reason it doesn't act like the deterministic machine it should be:

(defun number-pgraphs (start end) ;; alias M-npg
"insert paragraph-numbers of chapters at paragraphs' start in region. Blank lines have been guaranteed to consist of only a single C-j"
(interactive "r")
(save-excursion
(setq i 1) ;; current par. number
(goto-char start)
(while (< (point) end)
(forward-line)
(while (and (bolp) (eolp)) (forward-line))
;; skip blank line(s) with only linefeed chars
(if (not (= (char-after (point)) 42)) ;; not * character, start of new chapter
(progn
(insert (concat (number-to-string i) "." " "))
(setq i (1+ i)))
)))
) ;; defun

Chapters are *1, *2, *3 at bol, etc. to very many chapters and
all paragraphs are unfilled (one long line) and separated by minimal blank line (no white space). Paragraphs are numbered correctly at least 95% of the time (now and then they're all numbered but usually I have to add a few paragraph numbers at ends of chapters manually ) .
I was hoping to figure this out before manually editing the whole thing and maybe add an outer loop for chapters in order to process the whole file at once, but no such luck. After making many versions of the above defun, I have decided to escalate the problem.

my emacs is w64 of ver. 24-3-1

Thanks in advance for any help.

Ed

Gene

unread,
Jan 19, 2022, 8:18:31 PM1/19/22
to
On Monday, January 17, 2022 at 12:45:05 PM UTC-5, Btraven wrote:
> Dear Emacs gurus:
>
> I have been able to use the following elisp code to number paragraphs ...

As beheld as paragraphs qua `paragraphs'?

... in a plain text file ...

Didn't you just say paragraphs? Now you're talking about `text'.
With the advent of word processors the `paragraph' became a structure found in natural language as pandered-to within the domain of word-processing.

The `text' within the domain of the DSL known as elisp is merely a string of characters held in/by a buffer
Any sentence, `paragraph', or subsection you behold is -- as an elisp coder -- thus a figment of your imagination.

... but for some reason it doesn't act like the deterministic machine it should be:

You haven't found the DWIM instruction yet, I see. ;-)

I recommend an approach which allows you to exploit inverse processes via inverse functions.
Just as cons and car are inverses in about every member of the lisp family of programming languages (shy of Logo), there are -- in elisp -- functions which allow one to con(catenate) characters and others which allow a string to be deconstructed.

Also, as text files are comparatively small contrasted with music, video, and such there is usually no good reason to NOT maintain both recipe/meta text AND generated text which is seems you are presently messing with by inserting paragraph numbers on-the-fly.

If you can tentatively accept these two stratagems I recommend the following;
For recipe, meta text use the newline char to separate sentences.
Use double newline to separate paragraphs.
When viewing the resulting recipe text the human visual processing system perceives clumps of sentences as paragraphs, so this metaText, recipe format makes for a passible markup.
Experiment for yourself as actual mileage may vary.
It's worked for me for years, but I'm a weirdo who uses emacs instead of a word processor, so be advised.

Use mapconcat to glue sentences into paragraphs on an as-need basis to get the Look-and-feel you want.
Use split-string to split a human-readable paragraph into newline-delimited sentences of elisp data-structured recipe text.

Note that the by establishing constants for use in either delimiting or bonding it can be used for both.
Decomposing via split-string using, say, newline, can be inverted by using mapconcat with the same variable holding the newline character string.

When parsing your original text you're going to want to produce a list of paragraphs, which you will feed into a
(mapcar (lambda (paragraph)...) list-of-paragraphs)
which produces a nested list of paragraphs-cum-sentences.
Unless I'm mistaken, as I might be, as I'm assuming your brain and preferences are somewhat like mine as you're dabbling with natural-language text via elisp.

While implementing your system using this design strategy, you may observe that as you are already generating your desired human-readable text that your recipe text doesn't even have to qualify as text per se, but rather parameters vis-à-vis use or parametric equations implementable via functional programming.
Thus human readable text can be generated by evaluating elisp code.

And once a basic parser function employing split-string is established, as well as it's complementary generative function which can recompose the parsed data structure back into an acceptable facsimile of the original text, your pair of elisp functions can be embellished and developed via stepwise refinement.

Of course, the overarching field available for research is Natural Language Processing ... so feel free to glean tips and tricks as motivated.

Best of Luck,
Gene



Btraven

unread,
Jan 21, 2022, 1:14:36 PM1/21/22
to
Thanks, Gene, for all that food for thought. As far as dwim goes, I know that there are context dependent functions that attempt telepathic interpretation of user intentions but I have never tried to use any of them since they seem too advanced for me. What I refer to as a "paragraph" in my elisp code is just a line as seen by emacs forward-line function. It is separated from the next 'line' by two \n
From the behavior of my number-pgraph defun I am sure there must be some kind of logic leak going on, probably due to my faulty understanding of elisp. That routine processes text like:

*1 CHAPTER I

1. Not a day passes over the earth, but men and women of no note do great deeds, speak great words, and suffer noble sorrows. Of these obscure heroes, philosophers, and martyrs, the greater part will never be known till that hour, when many that are great shall be small, and the small great; but of others the world's knowledge may be said to sleep: their lives and characters lie hidden from nations in the annals that record them. The general reader cannot feel them, they are presented so curtly and coldly: they are not like breathing stories appealing to his heart, but little historic hail-stones striking him but to glance off his bosom: nor can he understand them; for epitomes are not narratives, as skeletons are not human figures.

2. Thus records of prime truths remain a dead letter to plain folk: the writers have left so much to the imagination, and imagination is so rare a gift. Here, then, the writer of fiction may be of use to the public — as an interpreter.
....

and so on, often to some line before the next * character, where it stops numbering the 'paragraphs' (lines).

So what I need is to have the defun number-pgraphs fixed rather than a new design.

Thanks, again,

Ed

Gene

unread,
Jan 25, 2022, 9:01:30 AM1/25/22
to
Given Piaget's notions of assimilation and accommodation, do you suppose you'd experience more grief modifying your creative process to accommodate numberex ... or to somehow shoe-horn numberx functionality into your sacrosanct creative process?

https://melpa.org/#/numbex

Btraven

unread,
Jan 26, 2022, 4:50:09 PM1/26/22
to
On Tuesday, January 25, 2022 at 9:01:30 AM UTC-5, Gene wrote:
> Given Piaget's notions of assimilation and accommodation, do you suppose you'd experience more grief modifying your creative process to accommodate numberex ... or to somehow shoe-horn numberx functionality into your sacrosanct creative process?
>
> https://melpa.org/#/numbex

Both would be way above my pay grade. It would require upgrading to ver. 26.1, setting lexical scope, reading and understanding code that uses many features that would require much study, and learning to use a very complex general purpose minor mode tool to solve a special problem. In short, it looks like overkill to me. Thanks anyway. I've downloaded the code and I will read it more carefully later.
In the meantime I added one line to my kludgey defun and that makes it work much better even though it sometimes fails to number the last few lines when there are more than about 100 paragraphs in a chapter:

(defun number-pgraphs (start end) ;; alias M-npg
"insert paragraph-numbers of chapters at paragraphs' start in region. Blank lines have been guaranteed to consist of only a single C-j"
(interactive "r")
(save-excursion
(setq i 1) ;; current par. number
(goto-char start)
(while (< (point) end)
(forward-line)
(while (and (bolp) (eolp)) (forward-line)) ;; skip blank line(s) with only linefeeds
(move-beginning-of-line nil) ;; added this which somehow numbered most chaps correctly
(if (not (= (char-after (point)) 42)) ;; not * character, start of new chapter
(progn
(insert (concat (number-to-string i) "." " "))
(setq i (1+ i)))
)))
) ;; defun

Another example from _The Betrothed_
....
68. “ Dovrei bene..... figliuoli no...... troppo presto..... ma la moglie.... se il mondo andasse come dovrebbe andare..... ”

69. “ Ah siete solo! Dunque abbiate pazienza, ma una porzione più piccola. ”

70. “ È giusto; ma se presto, come spero.... e con l’aiuto di Dio.... Basta; quando avessi moglie anch’io? ”

71. “ Allora si cambia il biglietto, e si cresce la porzione. Come v’ho detto; sempre in ragion delle bocche, ” disse lo sconosciuto, alzandosi.

72. “ Così va bene, ” gridò Renzo; e continuò, gridando e battendo il pugno sulla tavola: “ e perchè non la fanno una legge così? ”

73. “ Cosa volete che vi dica? Intanto vi do la buona notte, e me ne vo; perchè penso che la moglie e i figliuoli m’aspetteranno da un pezzo. ”

74. “ Un altro gocciolino, un altro gocciolino, ” gridava Renzo, riempiendo in fretta il bicchiere di colui; e subito alzatosi, e acchiappatolo per una falda del farsetto, tirava forte, per farlo seder di nuovo. “ Un altro gocciolino: non mi fate quest’affronto. ”
.....
Thanks, again, Gene but I think I need help from someone smarter than I but not as smart as you. :-)

Ed

Gene

unread,
Jan 28, 2022, 11:27:11 PM1/28/22
to
On Wednesday, January 26, 2022 at 4:50:09 PM UTC-5, Btraven wrote:
> On Tuesday, January 25, 2022 at 9:01:30 AM UTC-5, Gene wrote:
> > Given Piaget's notions of assimilation and accommodation, do you suppose you'd experience more grief modifying your creative process to accommodate numberex ... or to somehow shoe-horn numberx functionality into your sacrosanct creative process?
> >
> > https://melpa.org/#/numbex
> Both would be way above my pay grade.

Ya know ... I kinda experience the same sentiment, I suspect.
If one uses an out-of the-box, off-the-shelf configuration of emacs the parts seem to cooperate and dovetail better.
If one opts to attempt to pimp out one's working variant, BAD THINGS can happen.

If one uses the vanilla notion of a paragraph as something terminated with /n/n ... then tries to use numberx which allows the numbering of `examples' -- not paragraphs -- one is up against competing paradigms and has to use some dialectical process while merely HOPING -- against hope -- that some sort of synthesis CAN arise from reconciling theses, diatheses, ... different effing ways of representing things and doing-with vis-a-vis algorithmic glue which allows one to use an add-on package with extant data structures and functions.

From my perspective, this ain't a pay-grade problem so much as a gamble with one's time and sanity.

> It would require upgrading to ver. 26.1, setting lexical scope, reading and understanding code that uses many features that would require much study, and learning to use a very complex general purpose minor mode tool to solve a special problem. In short, it looks like overkill to me.

Seemingly ... from the perspective you just painted.

Thanks anyway. I've downloaded the code and I will read it more carefully later.

It's a teaser. If you could dream up an `example' in IT's worldview to map one-to-one and onto with your notion of a paragraph it would seem like you could use it as-is ... or with some mapping functions which map paragraph onto `example.

> In the meantime I added one line to my kludgey defun and that makes it work much better
> even though it sometimes fails to number the last few lines when there are more than about 100 paragraphs in a chapter:

We'll call it progress if it gets you a step or two out of the corner you found yourself painted into.

> (defun number-pgraphs (start end) ;; alias M-npg
> "insert paragraph-numbers of chapters at paragraphs' start in region. Blank lines have been guaranteed to consist of only a single C-j"
> (interactive "r")
> (save-excursion
> (setq i 1) ;; current par. number
> (goto-char start)
> (while (< (point) end)
> (forward-line)
> (while (and (bolp) (eolp)) (forward-line)) ;; skip blank line(s) with only linefeeds
> (move-beginning-of-line nil) ;; added this which somehow numbered most chaps correctly
> (if (not (= (char-after (point)) 42)) ;; not * character, start of new chapter
> (progn
> (insert (concat (number-to-string i) "." " "))
> (setq i (1+ i)))
> )))
> ) ;; defun

By way of stepwise refinement, promoting something closer to literate programming:

(1) Can the imperative code be reshaped or replaced with functional code?

(2) Can magic numbers -- such as 42 -- be replaced with semantically-suggestive descriptors, such as the-meaning-of-life ... or whatever you intend the reader of your literate program to `understand' or `resonate with' via conjoined fiction, folie à deux, or whatever your post-modernist authorial intent as an unreliable narrator is trying to induce in your audience.
(note: While taking an APL programming class back in the day I disdained the profs goading me to use descriptive variable names UNTIL I tried to read the code my former self had crafted just a few months prior. I had met the enemy and he was ME. APL effectively IS a write-only language. Are you going to recall what 42 `was' or `is a year or two down the road?)

(4) Use parametric equations/functions when possible. Rather than assume A buffer, even if only want to use your code in an implied buffer, allow the user of your RE-usable function to specify a buffer from any of those presently live. This allows mapcar and other functions to perform your magic on MANY enLISTED things-of-interest rather than just one identified via the conversational indexical `it' or `this'

Aside: I notice how you terminated your integer index numbers with one of the most overused and thus ambiguous terminators available: `."
What if you were to wrap your paragraph number in parentheticals -- such as {}, or [], for examples -- which disambiguate them as the unique paragraph identifiers you intend?
It would seem that a follow-on step could find then them ambiguously replace them as per the non-sensical-thou-standardized `traditional' language standards of the Language of the English.

But while your ideoglosical paracosm draft format were in use, you'd be better able to use automation via elisp while ignoring the procrustean standards of those kowtowing to standard problematic formatting conventions -- EG so-called `Natural' Language -- ... then performing a final step which keeps the language Nazi's from sending three consulting physicians to diagnose you with schizophrenia before calling in the guys with the straight jacket and a nice warm place with 3 hots, a cot, and drugs to make you heed the nonsense of the statistically normal people -- EG those with 100 IQ and an acquiescent attitude at the ready to pander to the normies and their norms.

> Thanks, again, Gene but I think I need help from someone smarter than I but not as smart as you. :-)

Were I merely `smart enough' I might have been more use during my first-pass response.
Sorry about that.
I didn't mean to either talk over your head or discourage you.

Best of luck in USING emacs for your intended purposes WHILE you augment your skills and abilities at pimping it out as you go.

Gene
0 new messages