all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Define skeleton from alist?
@ 2016-07-13  8:11 Paul Rankin
  2016-07-14  2:38 ` John Mastro
  0 siblings, 1 reply; 6+ messages in thread
From: Paul Rankin @ 2016-07-13  8:11 UTC (permalink / raw)
  To: help-gnu-emacs

Hello, does anyone really know their skeletons?

I'd like to create a skeleton with define-skeleton using strings from an alist. The skeleton should loop through the alist using the car of each element as both the prompt and first string inserted, then the cadr as initial value for user input.

The alist:

    (defcustom fountain-title-page-list
      (list (list "title" "")
            (list "credit" "written by")
            (list "author" user-full-name)
            (list "source" "")
            (list "date" "")
            (list "contact" user-mail-address))
      "Association list of strings used to create `fountain-title-page-skeleton'."
      :type '(repeat (group (string :tag "Key")
                            (string :tag "Initial value")))
      :group 'fountain)

My feeble non-functional attempt at the define-skeleton:

    (define-skeleton fountain-title-page-skeleton
      "Skeleton for inserting title page data.
    See `skeleton-insert'."
      nil
      '(dolist (var fountain-title-page-list
                    (list v1 v2 "\n"))
         (setq v1 (concat (car var) ": "))
         (setq v2 (skeleton-read v1 (cadr var)))))

Any help would be much appreciated.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Define skeleton from alist?
       [not found] <mailman.1264.1468397506.26859.help-gnu-emacs@gnu.org>
@ 2016-07-13 21:37 ` Gene
  2016-07-14  1:12   ` Paul Rankin
       [not found]   ` <mailman.1366.1468458751.26859.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 6+ messages in thread
From: Gene @ 2016-07-13 21:37 UTC (permalink / raw)
  To: help-gnu-emacs

At first blush it seems as you might have an impoverished mental model arising from an attitude and/or worldview in which Iteration, state-retention (EG via assignment via `setq'), and strings dominate.

Though `dolist' can iterate through a list, `mapcar' and its relatives can also access every element of a list.
You can think of `mapcar' as a higher order function analogous to a hand; it can hold any number of functions in it's tool-using hand ... even an on-the-fly anonymous lambda function.
When mapcar has a list element in it's hand the variants of c___r (with `car' and `cdr' qualifying as the simplest cases) can select subelements.

Thus I present the following for your `eval'uation:

(mapcar 'identity fountain-title-page-list)

(mapcar (lambda (elt)(identity elt)) fountain-title-page-list)

(mapcar (lambda (elt)(car elt)) fountain-title-page-list)

(mapcar (lambda (elt)(cdr elt)) fountain-title-page-list)

(mapcar (lambda (elt)(cons (car elt)(cdr elt))) fountain-title-page-list)

I'm hoping that what you learn can be used along with `concat' and `skeleton-read' to accomplish your desires.

Cheers!
  Gene


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Define skeleton from alist?
  2016-07-13 21:37 ` Define skeleton from alist? Gene
@ 2016-07-14  1:12   ` Paul Rankin
       [not found]   ` <mailman.1366.1468458751.26859.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 6+ messages in thread
From: Paul Rankin @ 2016-07-14  1:12 UTC (permalink / raw)
  To: help-gnu-emacs

Gene <gene.sullivan@gmail.com> on Wed, 13 Jul 2016 14:37 -0700:
> At first blush it seems as you might have an impoverished mental model

Okay.

> Thus I present the following for your `eval'uation:
> 
> (mapcar 'identity fountain-title-page-list)
> 
> (mapcar (lambda (elt)(identity elt)) fountain-title-page-list)
> 
> (mapcar (lambda (elt)(car elt)) fountain-title-page-list)
> 
> (mapcar (lambda (elt)(cdr elt)) fountain-title-page-list)
> 
> (mapcar (lambda (elt)(cons (car elt)(cdr elt))) fountain-title-page-list)

None of this produces a skeleton. See (info "(autotype) Skeleton Language")



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Define skeleton from alist?
  2016-07-13  8:11 Paul Rankin
@ 2016-07-14  2:38 ` John Mastro
  2016-07-14  6:00   ` Paul Rankin
  0 siblings, 1 reply; 6+ messages in thread
From: John Mastro @ 2016-07-14  2:38 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org

Paul Rankin <hello@paulwrankin.com> wrote:
> I'd like to create a skeleton with define-skeleton using strings from
> an alist. The skeleton should loop through the alist using the car of
> each element as both the prompt and first string inserted, then the
> cadr as initial value for user input.

I've never used skeleton but, from a quick look, it seems to me you
might be better served by a normal command. Is there a specific reason
you want/need to use skeleton?

If I understand correctly, this will achieve something like the final
result you want:

(defun fountain-title-page-function ()
  (interactive)
  (dolist (elt fountain-title-page-list)
    (let ((key (car elt))
          (val (cadr elt)))
      (insert key ": " (read-string (concat key ": ") val) "\n"))))

The reason this seems preferable to me, based on the stated problem, is
that it's impossible for a solution with skeleton to be much simpler
than the command above. By definition, the solution with skeleton will
still need a loop, etc.

Back to your question, I don't see how you could do it with
define-skeleton directly.

I looked at the implementation of define-skeleton, and it hands off the
work to a function called skeleton-proxy-new. I suppose you could call
it directly with something ugly like the below.

That's admittedly unsatisfying, so hopefully someone who actually knows
skeleton will be along with a better answer shortly.

(progn
  (put 'fountain-title-page-skeleton 'no-self-insert t)
  (defun fountain-title-page-skeleton (&optional str arg)
    (interactive "*P\nP")
    (skeleton-proxy-new
     `(nil ,@(let ((i 0))
               (apply #'append
                      (mapcar
                       (lambda (elt)
                         (let ((key (concat (car elt) ": "))
                               (val (cadr elt))
                               (sym (intern (format "v%d" (setq i (1+ i))))))
                           `(> ,key (setq ,sym (skeleton-read ,key ,val)) \n)))
                       fountain-title-page-list))))
     str arg)))

Hope that helps

        John



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Define skeleton from alist?
  2016-07-14  2:38 ` John Mastro
@ 2016-07-14  6:00   ` Paul Rankin
  0 siblings, 0 replies; 6+ messages in thread
From: Paul Rankin @ 2016-07-14  6:00 UTC (permalink / raw)
  To: help-gnu-emacs

John Mastro <john.b.mastro@gmail.com> on Wed, 13 Jul 2016 19:38 -0700:
> Paul Rankin <hello@paulwrankin.com> wrote:
> > I'd like to create a skeleton with define-skeleton using strings from
> > an alist. The skeleton should loop through the alist using the car of
> > each element as both the prompt and first string inserted, then the
> > cadr as initial value for user input.
> 
> I've never used skeleton but, from a quick look, it seems to me you
> might be better served by a normal command. Is there a specific reason
> you want/need to use skeleton?

I wanted to use a skeleton for auto-insert. It would appear define-auto-insert uses the skeleton language, but I would assume it can also be fed a command.

> If I understand correctly, this will achieve something like the final
> result you want:
> 
> (defun fountain-title-page-function ()
>   (interactive)
>   (dolist (elt fountain-title-page-list)
>     (let ((key (car elt))
>           (val (cadr elt)))
>       (insert key ": " (read-string (concat key ": ") val) "\n"))))

This works. Thank you. Although I ended up going with a static skeleton, because...

> The reason this seems preferable to me, based on the stated problem, is
> that it's impossible for a solution with skeleton to be much simpler
> than the command above. By definition, the solution with skeleton will
> still need a loop, etc.

It does seem like defining a skeleton from an arbitrarily long list is unduly difficult.

I wanted to use lisp expressions as initial values (e.g. (format-time-string "%F")) so in the end I figured it was unwise to go with a defcustom and then eval the cadrs. So I went with a static skeleton. More control for me, less for the user. Oh well.

Thanks for your help!



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Define skeleton from alist?
       [not found]   ` <mailman.1366.1468458751.26859.help-gnu-emacs@gnu.org>
@ 2016-07-15  1:13     ` Gene
  0 siblings, 0 replies; 6+ messages in thread
From: Gene @ 2016-07-15  1:13 UTC (permalink / raw)
  To: help-gnu-emacs

On Wednesday, July 13, 2016 at 9:12:33 PM UTC-4, Paul Rankin wrote:
> Gene on Wed, 13 Jul 2016 14:37 -0700:
> > At first blush it seems as you might have an impoverished mental model
> 
> Okay.
> 
> > Thus I present the following for your `eval'uation:
> > 
> > (mapcar 'identity fountain-title-page-list)
> > 
> > (mapcar (lambda (elt)(identity elt)) fountain-title-page-list)
> > 
> > (mapcar (lambda (elt)(car elt)) fountain-title-page-list)
> > 
> > (mapcar (lambda (elt)(cdr elt)) fountain-title-page-list)
> > 
> > (mapcar (lambda (elt)(cons (car elt)(cdr elt))) fountain-title-page-list)
> 
> None of this produces a skeleton. See (info "(autotype) Skeleton Language")

I'm not sure whether to respond with `Point taken' or `Really?'
If I were to acknowledge my failure to unequivocally reveal how `cons' can be used to CONStruct any/every list type -- alists and skeletons included -- then I'd have to concede my failure via `point taken'.
As the `cons' in the subexpression `(cons (car elt)(cdr elt))(cons (car elt)(cdr elt))' reveals how to CONStruct atomic elements into some of the components in both an alist and skeleton I might be tempted to chock this up to failure of imagination ... especially given that `car' and `cons' are inverses which allow analytical decomposition and synthetic composition, respectively.

The point of my one-liners was to reveal the low-level cons_cell-cum-list operators and how they can be used to both decompose and compose lists ... of which both alists and skeletons are -- arguably -- subspecies.

As strings are employed in Skeletons I'll provide the following inverses to reveal how to decompose then recompose a string encoding some of that info you suggested I read:
(let ; this be evaluated to generate a side-effect in the form of a demo 
(
 (string 
"Skeletons are an shorthand extension to the Lisp language, where various atoms directly perform either actions on the current buffer or rudimentary flow control mechanisms.  
Skeletons are interpreted by the function skeleton-insert.  

A skeleton is a list starting with an interactor, which is usually a prompt-string, or nil when not needed, but can also be a Lisp expression for complex read functions or for returning some calculated value.  
The rest of the list are any number of elements as described in the following table:"
 );string
 (sentence-end ".  ")
 (word-delimiter " ") 
 list-of-sentences
 list-of-words-within-sentences
 sentences-from-words
 paragraph-from-sentences
)

 (setq 
   list-of-sentences 
  (split-string ; the inverse of mapconcat 
    ; 'identity ; FUNCTION ; this argument is needed by mapconcat, though not split-string
    string ; STRING ... which corresponds with SEQUENCE after the string has been split to form a list useable by mapconcat
    sentence-end ; SEPARATORS ... which corresponds with SEPERATOR -- singular -- when used by mapconcat
  )
 )

 (setq
  list-of-words-within-sentences
  (mapcar
   (lambda (sentence)
    (split-string
     sentence
     word-delimiter
   ))
     list-of-sentences 
   )
 )
 
 (setq
   sentences-from-words
   (mapcar
    (lambda (list-of-words)
     (mapconcat ; the inverse of split-string when both use mutually-compatible arguments
      'identity ; FUNCTION used to concatenate substrings into larger, synthesized, composited strings
      list-of-words ; SEQUENCE
      word-delimiter ; SEPARATOR
    ))
   list-of-words-within-sentences
  )
 )

 (setq
   paragraph-from-sentences
   (list) ; to be replaced via (mapcar (lambda mapconcat)) FUNCTIONAL construct by those following the demo-cum-exercise
 )

 (list 
   (cons 'string string)
   (cons 'sentence-end sentence-end)
   (cons 'word-delimiter word-delimiter)
   (cons 'list-of-sentences list-of-sentences)
   (cons 'list-of-words-within-sentences list-of-words-within-sentences)
   (cons 'sentences-from-words sentences-from-words)
   (cons 'paragraph-from-sentences paragraph-from-sentences)
 )
)

I agree that I didn't provide a complete set of dots to connect.
I hope you'll agree that I DID provide `cons' as a means of ultimately connecting an ordered set of metaphorical dots, as well as `car' as a means -- perhaps recursively as with mapcar -- to decompose/deconstruct both partially and completely composed lists ... be they `be' or SEEM either alists or skeletons.
Reminder from info: "A skeleton is a list starting with ..."
Thus a skeleton as A LIST can be CONStructed via functional paradigm as well as statically created via the declarative paradigm.

I have responded to your admission "My feeble non-functional attempt at the define-skeleton: " as if you might be interested in clues on how you might bridge the gap between your essentially `declarative' first attempt and whatever perhaps-hybrid implementation you end up with.

Admittedly, perhaps you want a quick and direct solution which doesn't entail squandering time or getting your hands dirty at a lower-than-necessary level of detail.
If so ... NEVERMIND!

As John Mastro seems to have addressed your problem at a/the level you desired I suppose we can consider this issue closed.

Hopefully some of the from-the-ground-upwards and take-it-appart-then-put-it-back-together-again programmers out there might get some use out of my examples involving analytic-synthetic inverses.

Cheers!
  Gene

P.S. Although perhaps you personally have low to no interest in metaprogramming, I'll reveal that the use of the functional paradigm to CONStruct your otherwise static data structure put's one's mindset several steps closer to exploiting metaprogramming to CONStruct static-declarative -- TO THE REST OF THE WORLD -- `code'. 
Any/every alist and skeleton can be disassembled into a recipe via `car' and its relatives in the `mapcar' family.
Then this recipe -- using `cons' to correspond with the `car' function used to disassemble either the alist or skeleton -- can be `eval'uated to produce the quasiStatic data structure originally implemented -- if not conceived -- via the declarative paradigm.

In a sentence, one can start with a Cathedral then disassemble its structure to produce a recipe for a next-generation Cathedral ... never having to settle for a helter skelter bazaar.

G


/pedantic tripe


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-07-15  1:13 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.1264.1468397506.26859.help-gnu-emacs@gnu.org>
2016-07-13 21:37 ` Define skeleton from alist? Gene
2016-07-14  1:12   ` Paul Rankin
     [not found]   ` <mailman.1366.1468458751.26859.help-gnu-emacs@gnu.org>
2016-07-15  1:13     ` Gene
2016-07-13  8:11 Paul Rankin
2016-07-14  2:38 ` John Mastro
2016-07-14  6:00   ` Paul Rankin

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.