unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Generalize and standarize dired-plural-s
@ 2016-09-18 14:00 Tino Calancha
  2016-09-18 15:06 ` Kaushal Modi
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Tino Calancha @ 2016-09-18 14:00 UTC (permalink / raw)
  To: Emacs developers; +Cc: tino.calancha


Hi,

I)
dired.el introduces the function `dired-plural-s' to pluralize
correctly output messages as:
(format "Kill Dired buffer%s of %s, too? "
         (dired-plural-s (length buf-list))
         (file-name-nondirectory fn))

In this example, it returns "s" if (length buf-list) > 1.  Otherwise,
it returns "".
Of course, this task is not exclusive of Dired: many other packages
in Emacs source code do the same thing.

II)
As you know, for some words the plural is different that just
appending "s" to the end.  For instance, in message.el:
(format
  "Really use %s possibly unknown group%s: %s? "
  (if (= (length errors) 1) "this" "these")
  (if (= (length errors) 1) "" "s")
  (mapconcat 'identity errors ", "))

"this" -> "these" is not handled by `dired-plural-s'.

I am wondering if it has sense to add a standard function, 
`string-plural-s', covering both cases: I), II).  Then, we might do
`dired-plural-s' and alias for the new function.
We might update all the 'plularizations' in Emacs source code to use
the new function as well.

Following function could do the job:

(defun string-plural-s (arg &optional string plural)
   "\
Return plural of STRING if ARG is nil, or an integer >1, or a seq of 
length >1.
If ARG is =1 or a sequence of length =1, return STRING.
Optional arg PLURAL is the plural of STRING.
If STRING is nil, return \"s\" or \"\"."
   (let ((single (or string ""))
         (plural (if (and string plural) plural
                   (apply #'string (append string "s" nil)))))
     (cond ((natnump arg)
            (if (= arg 1) single plural))
           ((null arg) plural)
           ((consp arg)
            (if (null (cdr arg)) single plural))
           ((arrayp arg)
            (if (= (length arg) 1) single plural))
           (t
            (signal 'wrong-type-argument
                    (list arg 'natnump 'listp 'arrayp))))))


What do you think about this idea?

Regards,
Tino



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

* Re: Generalize and standarize dired-plural-s
  2016-09-18 14:00 Generalize and standarize dired-plural-s Tino Calancha
@ 2016-09-18 15:06 ` Kaushal Modi
  2016-09-18 15:12 ` Drew Adams
  2016-09-18 17:45 ` Yuri Khan
  2 siblings, 0 replies; 6+ messages in thread
From: Kaushal Modi @ 2016-09-18 15:06 UTC (permalink / raw)
  To: Tino Calancha, Emacs developers

[-- Attachment #1: Type: text/plain, Size: 3224 bytes --]

On Sun, Sep 18, 2016, 10:00 AM Tino Calancha <tino.calancha@gmail.com>
wrote:

>
> Hi,
>
> I)
> dired.el introduces the function `dired-plural-s' to pluralize
> correctly output messages as:
> (format "Kill Dired buffer%s of %s, too? "
>          (dired-plural-s (length buf-list))
>          (file-name-nondirectory fn))
>
> In this example, it returns "s" if (length buf-list) > 1.  Otherwise,
> it returns "".
> Of course, this task is not exclusive of Dired: many other packages
> in Emacs source code do the same thing.
>

I agree. I have also had something in my emacs config that made me wish of
the existence of a function like this.


> II)
> As you know, for some words the plural is different that just
> appending "s" to the end.  For instance, in message.el:
> (format
>   "Really use %s possibly unknown group%s: %s? "
>   (if (= (length errors) 1) "this" "these")
>   (if (= (length errors) 1) "" "s")
>   (mapconcat 'identity errors ", "))
>
> "this" -> "these" is not handled by `dired-plural-s'.
>
> I am wondering if it has sense to add a standard function,
> `string-plural-s', covering both cases: I), II).


+1


> Then, we might do
> `dired-plural-s' and alias for the new function.
> We might update all the 'plularizations' in Emacs source code to use
> the new function as well.
>
> Following function could do the job:
>
> (defun string-plural-s (arg &optional string plural)
>    "\
> Return plural of STRING if ARG is nil, or an integer >1, or a seq of
> length >1.
> If ARG is =1 or a sequence of length =1, return STRING.
> Optional arg PLURAL is the plural of STRING.
> If STRING is nil, return \"s\" or \"\"."
>    (let ((single (or string ""))
>          (plural (if (and string plural) plural
>                    (apply #'string (append string "s" nil)))))
>      (cond ((natnump arg)
>             (if (= arg 1) single plural))
>            ((null arg) plural)
>            ((consp arg)
>             (if (null (cdr arg)) single plural))
>            ((arrayp arg)
>             (if (= (length arg) 1) single plural))
>            (t
>             (signal 'wrong-type-argument
>                     (list arg 'natnump 'listp 'arrayp))))))


>
> What do you think about this idea?
>

I like this idea.

The only comment I have is that the "append 's' to pluralize" part should
not be hard-coded into the string-plural-s function.

How about have a "string-plural--conditions-function" variable (or
something named like that), and then you funcall that variable in
string-plural-s?

The "string-plural--conditions-function" variable would be a lambda
function that would accept an arg STRING and output a plural string for
that STRING.

Inside the lambda, would be an elaborate cond form that would decide how to
pluralize the string

this -> these
grape -> grapes
knife -> knives
ruby -> rubies
sheep -> sheep

This  "string-plural--conditions-function" variable will be quite an
elaborate cond form as it would try to cover all the corner cases of
English pluralization. I am suggesting this to be a separate function so
that the logic of string-plural-s stays clear and succinct and the English
grammar rules do not come in the way while understanding that function.

-- 

Kaushal Modi

[-- Attachment #2: Type: text/html, Size: 4790 bytes --]

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

* RE: Generalize and standarize dired-plural-s
  2016-09-18 14:00 Generalize and standarize dired-plural-s Tino Calancha
  2016-09-18 15:06 ` Kaushal Modi
@ 2016-09-18 15:12 ` Drew Adams
  2016-09-18 17:45 ` Yuri Khan
  2 siblings, 0 replies; 6+ messages in thread
From: Drew Adams @ 2016-09-18 15:12 UTC (permalink / raw)
  To: Tino Calancha, Emacs developers

> I am wondering if it has sense to add a standard function,
> `string-plural-s', covering both cases: I), II).  Then, we might do
> `dired-plural-s' and alias for the new function.
> We might update all the 'plularizations' in Emacs source code to use
> the new function as well. What do you think about this idea?

I'd like to see `format' extended along the lines of Common Lisp.

http://www.lispworks.com/documentation/HyperSpec/Body/22_chc.htm



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

* Re: Generalize and standarize dired-plural-s
  2016-09-18 14:00 Generalize and standarize dired-plural-s Tino Calancha
  2016-09-18 15:06 ` Kaushal Modi
  2016-09-18 15:12 ` Drew Adams
@ 2016-09-18 17:45 ` Yuri Khan
  2016-09-18 19:28   ` Tino Calancha
  2 siblings, 1 reply; 6+ messages in thread
From: Yuri Khan @ 2016-09-18 17:45 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Emacs developers

On Sun, Sep 18, 2016 at 9:00 PM, Tino Calancha <tino.calancha@gmail.com> wrote:

> I am wondering if it has sense to add a standard function,
> `string-plural-s'

> (defun string-plural-s (arg &optional string plural)
>   "\
> Return plural of STRING if ARG is nil, or an integer >1, or a seq of length
>>1.
> If ARG is =1 or a sequence of length =1, return STRING.
> Optional arg PLURAL is the plural of STRING.
> If STRING is nil, return \"s\" or \"\"."

The two previous replies in this thread suggest, respectively,
shipping a dictionary of English irregular plurals, and implementing a
mini-language suitable for encoding some but not all English plurals.
(E.g. -f[e] → -ves, -x → -xen are not covered.)

I think the original proposal (requiring both forms to be spelled in
full or falling back to regular plural by passing a nil STRING) is
cheaper to implement and more flexible than a hardcoded dictionary,
and makes for more readable strings in source code than ~P ~:P ~@P
~:@P.

It is also easier to extend to other languages, if and when we deem it
necessary. (It would require passing an additional argument to specify
language, and more forms (singular, dual, trial, paucal, plural).)

I also suggest that the function be split in two: a core function
dealing with integers only, and a convenience wrapper that also
accepts sequences.



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

* Re: Generalize and standarize dired-plural-s
  2016-09-18 17:45 ` Yuri Khan
@ 2016-09-18 19:28   ` Tino Calancha
  2016-09-18 20:47     ` Yuri Khan
  0 siblings, 1 reply; 6+ messages in thread
From: Tino Calancha @ 2016-09-18 19:28 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Emacs developers, Tino Calancha



On Sun, 18 Sep 2016, Yuri Khan wrote:

> It is also easier to extend to other languages, if and when we deem it
> necessary. (It would require passing an additional argument to specify
> language, and more forms (singular, dual, trial, paucal, plural).)
>
> I also suggest that the function be split in two: a core function
> dealing with integers only, and a convenience wrapper that also
> accepts sequences.

Thank you Yuri for your suggstions.
Something like this? With the additional forms and the language argument
keep unimplemented:

(defsubst string--plural-s-1 (arg singular plural _dual _trial _paucal _lang)
   (if (= arg 1) singular plural))

(defun string--plural-s-2 (arg singular plural _dual _trial _paucal _lang)
   (cond ((null arg) plural)
         ((consp arg)
          (if (null (cdr arg)) singular plural))
         ((arrayp arg)
          (if (= (length arg) 1) singular plural))))

(defun string-plural-s (arg &optional string plural dual trial paucal lang)
   "\
Return plural of STRING if ARG is nil, or an integer >1, or a seq of 
length >1.
If ARG is =1 or a sequence of length =1, return STRING.
If STRING is nil, return \"s\" or \"\".
Optional arg PLURAL is the plural of STRING.
Optional arg DUAL is the =dual of STRING.
Optional arg TRIAL is the trial of STRING.
Optional arg PAUCAL is the paucal of STRING.
Optional arg LANG is the language of STRING.  Default to english."
   (let ((sin (or string ""))
         (plu (if (and string plural) plural
                (apply #'string (append string "s" nil)))))
     (cond ((natnump arg)
            (string--plural-s-1 arg sin plu dual trial paucal lang))
           ((sequencep arg)
            (string--plural-s-2 arg sin plu dual trial paucal lang))
           (t
            (signal 'wrong-type-argument
                    (list arg 'natnump 'listp 'arrayp))))))




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

* Re: Generalize and standarize dired-plural-s
  2016-09-18 19:28   ` Tino Calancha
@ 2016-09-18 20:47     ` Yuri Khan
  0 siblings, 0 replies; 6+ messages in thread
From: Yuri Khan @ 2016-09-18 20:47 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Emacs developers

On Mon, Sep 19, 2016 at 2:28 AM, Tino Calancha <tino.calancha@gmail.com> wrote:

>> It is also easier to extend to other languages, if and when we deem it
>> necessary. (It would require passing an additional argument to specify
>> language, and more forms (singular, dual, trial, paucal, plural).)
>>
>> I also suggest that the function be split in two: a core function
>> dealing with integers only, and a convenience wrapper that also
>> accepts sequences.
>
> Thank you Yuri for your suggstions.
> Something like this? With the additional forms and the language argument
> keep unimplemented:

There’s not yet consensus on whether language support is desired, so
feel free to disregard the following. (The issue of providing Emacs
localization has been raised previously; the argument against is that
the Emacs UI consists not only of messages but also command names and
localizing those is harmful, see Microsoft Excel for an example of
what happens.)


Hypothetically, if it is…

At the lowest level, we’d need functions implementing the actual
selection for all supported languages. Untested, not-well-thought,
head-to-fingers-to-mail-client code follows:

(defun string-plural-japanese (_arg forms)
  (car forms))

(defun string-plural-english (arg forms)
  (if (= arg 1) (car forms) (cadr forms)))

(defun string-plural-russian (arg forms)
  (pcase forms (`(,singular ,dual ,plural . ,_)
    (pcase (list (% (/ arg 10) 10) (% arg 10))
      (`(1 ,_ones) plural)
      (`(,_tens 1) singular)
      (`(,_tens 2) dual)
      (`(,_tens 3) dual)
      (`(,_tens 4) dual)
      (`(,_tens ,_ones) plural)))))

I avoid assigning fixed positions for each form, for two reasons:

* not all languages use all forms;
* fixed positions are brittle in case we need to add a language with
even more forms.

Note how the selection logic can be complicated. Generally, taking the
length of a list is not avoidable; in Russian, a list of 1001 things
still wants the singular form while 1000 wants plural.

The wrapper function could accept the language worker function
directly as an argument:

(defun string-plural (lang arg &rest forms)
  "<…docstring…>"
  (cond
    ((natnump arg) (lang arg forms))
    ((sequencep arg) (lang (length arg) forms))
    (t (error "<…some useful message…>"))))

However, this makes for clumsy usage syntax:

(message "%d %s of beer on the wall"
         10
         (string-plural string-plural-english 10 "bottle" "bottles"))

So maybe LANG could be a string serving as a key into an alist…

(defvar string-plural-languages
  (("ja" . string-plural-japanese)
   ("en" . string-plural-english)
   ("ru" . string-plural-russian)))

(defun string-plural (lang arg &rest forms)
  "<…docstring…>"
  (let ((lang-function
         (cond
           ((stringp lang) (assoc lang string-plural-languages))
           ((functionp lang) lang)
           (t (error "…")))))
    (cond
      ((natnump arg) (lang-function arg forms))
      ((sequencep arg) (lang-function (length arg) forms))
      (t (error "<…some useful message…>"))))

(message "%d %s of beer on the wall"
         10
         (string-plural "en" 10 "bottle" "bottles"))



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

end of thread, other threads:[~2016-09-18 20:47 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-18 14:00 Generalize and standarize dired-plural-s Tino Calancha
2016-09-18 15:06 ` Kaushal Modi
2016-09-18 15:12 ` Drew Adams
2016-09-18 17:45 ` Yuri Khan
2016-09-18 19:28   ` Tino Calancha
2016-09-18 20:47     ` Yuri Khan

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).