[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Generalize and standarize dired-plural-s

From: Yuri Khan
Subject: Re: Generalize and standarize dired-plural-s
Date: Mon, 19 Sep 2016 02:47:18 +0600

On Mon, Sep 19, 2016 at 2:28 AM, Tino Calancha <address@hidden> 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)
    ((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"
         (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)
  (let ((lang-function
           ((stringp lang) (assoc lang string-plural-languages))
           ((functionp lang) lang)
           (t (error "…")))))
      ((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"
         (string-plural "en" 10 "bottle" "bottles"))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]