\concat markup command

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

\concat markup command

Werner LEMBERG

All markup commands which accept more than a single markup put spaces
inbetween.  However, sometimes this is not useful (for example, just
look at the bad appearance of the E=mc² -- there is an incorrect space
before the superscript 2.

I thus suggest a command \concat which does the same as \line but
without inserting whitespace:

  #(define-markup-command (concat layout props args) (markup-list?)
    "Concatenate @var{args} in a horizontal line, without spaces inbetween."
    (let*
        ((stencils (map (lambda (m) (interpret-markup layout props m)) args))
         (text-dir (chain-assoc-get 'text-direction props RIGHT))
        )

      (if (= text-dir LEFT)
          (set! stencils (reverse stencils)))

      (stack-stencil-line
       0
       (remove ly:stencil-empty? stencils))))

I can add this if you want me to do so.


   Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Han-Wen Nienhuys-2
Werner LEMBERG escreveu:
> All markup commands which accept more than a single markup put spaces
> inbetween.  However, sometimes this is not useful (for example, just
> look at the bad appearance of the E=mc² -- there is an incorrect space
> before the superscript 2.
>
> I thus suggest a command \concat which does the same as \line but
> without inserting whitespace:

> I can add this if you want me to do so.


Isn't this more efficiently done by setting word-space to 0.0 and
interpreting as a line?

--

Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
  -- Code for Music Notation
http://www.lilypond-design.com



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG

> > I thus suggest a command \concat which does the same as \line but
> > without inserting whitespace:
>
> Isn't this more efficiently done by setting word-space to 0.0 and
> interpreting as a line?

Isn't this what my command does?  What do you mean with `efficiently'?


    Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Han-Wen Nienhuys-2
Werner LEMBERG escreveu:
>>> I thus suggest a command \concat which does the same as \line but
>>> without inserting whitespace:
>> Isn't this more efficiently done by setting word-space to 0.0 and
>> interpreting as a line?
>
> Isn't this what my command does?  What do you mean with `efficiently'?
>

I mean: use make-line-markup , prepending '((word-space . 0.0)) onto the
property list.

--

Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
  -- Code for Music Notation
http://www.lilypond-design.com



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG

> > Isn't this what my command does?  What do you mean with
> > `efficiently'?
>
> I mean: use make-line-markup , prepending '((word-space . 0.0)) onto
> the property list.

Example code, please.  I had the impression that changing word-space
is a global operation...


    Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Han-Wen Nienhuys-2
Werner LEMBERG escreveu:
>>> Isn't this what my command does?  What do you mean with
>>> `efficiently'?
>> I mean: use make-line-markup , prepending '((word-space . 0.0)) onto
>> the property list.
>
> Example code, please.  I had the impression that changing word-space
> is a global operation...

each markup gets an argument props which is an alist of alists.
If you look into define-markups.scm, you'll see loads of commands that
do prepend-alist-chain to bolt extra properties onto that.
see eg. tied-lyric

>
>     Werner
>


--

Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
  -- Code for Music Notation
http://www.lilypond-design.com



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Erik Sandberg-2
In reply to this post by Han-Wen Nienhuys-2
On Saturday 11 November 2006 23:53, Han-Wen Nienhuys wrote:

> Werner LEMBERG escreveu:
> > All markup commands which accept more than a single markup put spaces
> > inbetween.  However, sometimes this is not useful (for example, just
> > look at the bad appearance of the E=mc² -- there is an incorrect space
> > before the superscript 2.
> >
> > I thus suggest a command \concat which does the same as \line but
> > without inserting whitespace:
> >
> > I can add this if you want me to do so.
>
> Isn't this more efficiently done by setting word-space to 0.0 and
> interpreting as a line?

BTW: What about ligatures? What should \concat { f i } produce?

--
Erik



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG

> BTW: What about ligatures? What should \concat { f i } produce?

Good question.  Perhaps `\concat { f i }' should be really identical
to `fi', contrary to \line with word-space set to zero...

Han-Wen?


    Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Han-Wen Nienhuys-2
Werner LEMBERG escreveu:
>> BTW: What about ligatures? What should \concat { f i } produce?
>
> Good question.  Perhaps `\concat { f i }' should be really identical
> to `fi', contrary to \line with word-space set to zero...
>
> Han-Wen?

It's your call. You could try to inspect the arguments, and if they are
strings or simple markups, concatenate the strings.

--

Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
  -- Code for Music Notation
http://www.lilypond-design.com



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG
In reply to this post by Han-Wen Nienhuys-2

> >>> Isn't this what my command does?  What do you mean with
> >>> `efficiently'?
> >> I mean: use make-line-markup , prepending '((word-space . 0.0))
> >> onto the property list.
> >
> > Example code, please.  I had the impression that changing
> > word-space is a global operation...
>
> each markup gets an argument props which is an alist of alists.  If
> you look into define-markups.scm, you'll see loads of commands that
> do prepend-alist-chain to bolt extra properties onto that.  see
> eg. tied-lyric

I've done a closer look now, and I see that your suggestion doesn't
work that well -- make-line-markup accepts only a single argument,
while I need to process a list of markups...


    Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG
> I've done a closer look now, and I see that your suggestion doesn't
> work that well -- make-line-markup accepts only a single argument,
> while I need to process a list of markups...

Please forget that.  I was confused.


    Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG
In reply to this post by Han-Wen Nienhuys-2

> > Good question.  Perhaps `\concat { f i }' should be really
> > identical to `fi', contrary to \line with word-space set to
> > zero...
>
> It's your call.  You could try to inspect the arguments, and if they
> are strings or simple markups, concatenate the strings.

OK, here it is.  Please comment -- especially my Scheme code since I'm
not really acquainted with it.


    Werner


======================================================================


#(define-markup-command (concat layout props args) (markup-list?)
  "Concatenate @var{args} in a horizontal line, without spaces inbetween.
Strings and simple markups are concatenated on the input level, allowing
ligatures.  For example, @code{\\concat @{ \"f\" \\simple #\"i\" @}} is
equivalent to @code{\"fi\"}."

  (define (concat-string-args arg-list)
    (do ((arg-list arg-list (cdr arg-list))
         (result-list '() result-list)
         (result #f (car result-list)))
        ((null? arg-list) (reverse result-list))
      (let ((arg (car arg-list)))
        (if (and (pair? arg) (eqv? (car arg) simple-markup))
          (set! arg (cadr arg)))
        (if (and (string? result) (string? arg))
            (set! result-list (cons (string-append result arg)
                                    (cdr result-list)))
          (set! result-list (cons arg result-list))))))

  (interpret-markup layout
                    (prepend-alist-chain 'word-space 0 props)
                    (make-line-markup (concat-string-args args))))

\relative {
  c-\markup { \concat { "f" "i" } \concat { "f" \null "i" } }
  c-\markup { \concat { "j" } }
  c-\markup { \concat { \tiny { "k" } } }
  c-\markup { \concat { \simple #"f" \simple #"i" } }
}


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Han-Wen Nienhuys-2
Werner LEMBERG escreveu:
>>> Good question.  Perhaps `\concat { f i }' should be really
>>> identical to `fi', contrary to \line with word-space set to
>>> zero...
>> It's your call.  You could try to inspect the arguments, and if they
>> are strings or simple markups, concatenate the strings.
>
> OK, here it is.  Please comment -- especially my Scheme code since I'm
> not really acquainted with it.

> #(define-markup-command (concat layout props args) (markup-list?)
>   "Concatenate @var{args} in a horizontal line, without spaces inbetween.
> Strings and simple markups are concatenated on the input level, allowing
> ligatures.  For example, @code{\\concat @{ \"f\" \\simple #\"i\" @}} is
> equivalent to @code{\"fi\"}."
>
>   (define (concat-string-args arg-list)
>     (do ((arg-list arg-list (cdr arg-list))
>          (result-list '() result-list)
>          (result #f (car result-list)))
>         ((null? arg-list) (reverse result-list))
>       (let ((arg (car arg-list)))
>         (if (and (pair? arg) (eqv? (car arg) simple-markup))
>           (set! arg (cadr arg)))
>         (if (and (string? result) (string? arg))
>             (set! result-list (cons (string-append result arg)
>                                     (cdr result-list)))
>           (set! result-list (cons arg result-list))))))


This is unschemey. I think it's better to use a
a functional approach. The signature should probably be something like

 (concat-string-args args-todo done)


and have a recursion

 (concat-string-args (cdr args-todo)
                     (if (string? ..)
                         ..string-append onto (car done)..
                         (cons (car args-todo) done)))

another option is to use fold-left or fold-right (srfi-1 IIRC) to do
the list looping

--

Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG

> This is unschemey.

Ha!  It took me *hours* to get this small snippet right :-(

> I think it's better to use a
> a functional approach.

Will have a look.  However, my solution works quite fine, and I
probably don't have enough time to get it `right'.


    Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG
In reply to this post by Han-Wen Nienhuys-2

> another option is to use fold-left or fold-right (srfi-1 IIRC) to do
> the list looping

Ok, here's another try.  However, look how `result' is set in the
first `let' block -- what about adding safe-car and safe-cdr (on the
C++ level) which don't signal an error if its argument is the empty
list?  The Elisp versions of car and cdr do this by default...


    Werner

======================================================================

#(define-markup-command (concat layout props args) (markup-list?)
  "Concatenate @var{args} in a horizontal line, without spaces inbetween.
Strings and simple markups are concatenated on the input level, allowing
ligatures.  For example, @code{\\concat @{ \"f\" \\simple #\"i\" @}} is
equivalent to @code{\"fi\"}."

  (define (concat-string-args arg-list)
    (fold-right (lambda (arg result-list)
                  (let ((result (if (pair? result-list)
                                    (car result-list)
                                  '())))
                    (if (and (pair? arg) (eqv? (car arg) simple-markup))
                      (set! arg (cadr arg)))
                    (if (and (string? result) (string? arg))
                        (cons (string-append arg result) (cdr result-list))
                      (cons arg result-list))))
                '()
                arg-list))

  (interpret-markup layout
                    (prepend-alist-chain 'word-space 0 props)
                    (make-line-markup (concat-string-args args))))


\relative {
  c-\markup { \concat { "f" "i" } \concat { "f" \null "i" } }
  c-\markup { \concat { "j" } }
  c-\markup { \concat { \tiny { "k" } } }
  c-\markup { \concat { "f" \simple #"i" } }
}


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Han-Wen Nienhuys-2
Werner LEMBERG escreveu:
>> another option is to use fold-left or fold-right (srfi-1 IIRC) to do
>> the list looping
>
> Ok, here's another try.  However, look how `result' is set in the
> first `let' block -- what about adding safe-car and safe-cdr (on the
> C++ level) which don't signal an error if its argument is the empty
> list?  The Elisp versions of car and cdr do this by default...

In scheme, it's less clear what such a function should return; #f
(false) and '() (end of list) are distinct.

Can you push this change after adding it to one of the markup
regtests?


--

Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Werner LEMBERG

> Can you push this change after adding it to one of the markup
> regtests?

Done.  Shall I prepare an entry for the NEWS file also?


    Werner


_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel
Reply | Threaded
Open this post in threaded view
|

Re: \concat markup command

Han-Wen Nienhuys-2
Werner LEMBERG escreveu:
>> Can you push this change after adding it to one of the markup
>> regtests?
>
> Done.  Shall I prepare an entry for the NEWS file also?

I think the feature is too minor to put in the NEWS file, but if you think otherwise....


--

Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

LilyPond Software Design
 -- Code for Music Notation
http://www.lilypond-design.com



_______________________________________________
lilypond-devel mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/lilypond-devel