Raymond Toy pushed to branch issue-139-add-alias-local-external-format at cmucl / cmucl
Commits:
-
7bbb4843
by Raymond Toy at 2022-11-08T03:19:19+00:00
-
68f4ec70
by Raymond Toy at 2022-11-08T03:19:21+00:00
-
23f66902
by Raymond Toy at 2022-11-14T05:09:37+00:00
-
6764053d
by Raymond Toy at 2022-11-14T05:09:38+00:00
-
0a2144aa
by Raymond Toy at 2022-11-14T14:38:55-08:00
-
10f6311f
by Raymond Toy at 2022-11-14T14:49:31-08:00
6 changed files:
- src/code/commandline.lisp
- src/code/intl.lisp
- src/code/unix.lisp
- src/general-info/release-21e.md
- src/lisp/os-common.c
- tests/issues.lisp
Changes:
... | ... | @@ -339,16 +339,54 @@ |
339 | 339 | (defun help-switch-demon (switch)
|
340 | 340 | (declare (ignore switch))
|
341 | 341 | (format t (intl:gettext "~&Usage: ~A <options>~2%") *command-line-utility-name*)
|
342 | - (dolist (s (sort *legal-cmd-line-switches* #'string<
|
|
343 | - :key #'car))
|
|
344 | - (destructuring-bind (name doc arg)
|
|
345 | - s
|
|
346 | - (format t " -~A ~@[~A~]~%" name (if arg (intl:gettext arg)))
|
|
347 | - ;; Poor man's formatting of the help string
|
|
348 | - (with-input-from-string (stream (intl:gettext doc))
|
|
349 | - (loop for line = (read-line stream nil nil)
|
|
350 | - while line
|
|
351 | - do (format t "~8T~A~%" line)))))
|
|
342 | + (flet
|
|
343 | + ((get-words (s)
|
|
344 | + (declare (string s))
|
|
345 | + ;; Return a list of all the words from S. A word is defined
|
|
346 | + ;; as any sequence of characters separated from others by
|
|
347 | + ;; whitespace consisting of space, newline, tab, formfeed, or
|
|
348 | + ;; carriage return.
|
|
349 | + (let ((end (length s)))
|
|
350 | + (loop for left = 0 then (+ right 1)
|
|
351 | + for right = (or
|
|
352 | + (position-if #'(lambda (c)
|
|
353 | + (member c
|
|
354 | + '(#\space #\newline #\tab #\ff #\cr)))
|
|
355 | + s
|
|
356 | + :start left)
|
|
357 | + end)
|
|
358 | + ;; Collect the word bounded by left and right in a list.
|
|
359 | + unless (and (= right left))
|
|
360 | + collect (subseq s left right) into subseqs
|
|
361 | + ;; Keep going until we reach the end of the string.
|
|
362 | + until (>= right end)
|
|
363 | + finally (return subseqs)))))
|
|
364 | + |
|
365 | + (dolist (s (sort *legal-cmd-line-switches* #'string<
|
|
366 | + :key #'car))
|
|
367 | + (destructuring-bind (name doc arg)
|
|
368 | + s
|
|
369 | + (format t " -~A ~@[~A~]~%" name (if arg (intl:gettext arg)))
|
|
370 | + ;; Poor man's formatting of the help string
|
|
371 | + (let ((*print-right-margin* 80))
|
|
372 | + ;; Extract all the words from the string and print them out
|
|
373 | + ;; one by one with a space between each, wrapping the output
|
|
374 | + ;; if needed. Each line is indented by 8 spaces.
|
|
375 | + ;;
|
|
376 | + ;; "~@< ~@;"
|
|
377 | + ;; per-line prefix of spaces and pass the whole arg list
|
|
378 | + ;; to this directive.
|
|
379 | + ;;
|
|
380 | + ;; "~{~A~^ ~}"
|
|
381 | + ;; loop over each word and print out the word followed by
|
|
382 | + ;; a space.
|
|
383 | + ;;
|
|
384 | + ;; "~:@>"
|
|
385 | + ;; No suffix, and insert conditional newline after each
|
|
386 | + ;; group of blanks if needed.
|
|
387 | + (format t "~@< ~@;~{~A~^ ~}~:@>"
|
|
388 | + (get-words (intl:gettext doc))))
|
|
389 | + (terpri))))
|
|
352 | 390 | (ext:quit))
|
353 | 391 |
|
354 | 392 | (defswitch "help" #'help-switch-demon
|
... | ... | @@ -520,10 +520,7 @@ |
520 | 520 | |
521 | 521 | (defun setlocale (&optional locale)
|
522 | 522 | (setf *locale* (or locale
|
523 | - (getenv "LANGUAGE")
|
|
524 | - (getenv "LC_ALL")
|
|
525 | - (getenv "LC_MESSAGES")
|
|
526 | - (getenv "LANG")
|
|
523 | + (unix::unix-get-lc-messages)
|
|
527 | 524 | *locale*)))
|
528 | 525 | |
529 | 526 | (defmacro textdomain (domain)
|
... | ... | @@ -2900,6 +2900,22 @@ |
2900 | 2900 | (alien:extern-alien "os_setlocale"
|
2901 | 2901 | (function c-call:int))))
|
2902 | 2902 | |
2903 | +(defun unix-get-lc-messages ()
|
|
2904 | + _N"Get LC_MESSAGES from the current locale. If we can't, return
|
|
2905 | + NIL. A call to UNIX-SETLOCALE must have been done previously before
|
|
2906 | + calling this so that the correct locale is returned."
|
|
2907 | + (with-alien ((buf (array c-call:char 256)))
|
|
2908 | + (let ((result
|
|
2909 | + (alien-funcall
|
|
2910 | + (extern-alien "os_get_lc_messages"
|
|
2911 | + (function c-call:int
|
|
2912 | + (* c-call:char)
|
|
2913 | + c-call:int))
|
|
2914 | + (cast buf (* c-call:char))
|
|
2915 | + 256)))
|
|
2916 | + (when (zerop result)
|
|
2917 | + (cast buf c-call:c-string)))))
|
|
2918 | + |
|
2903 | 2919 | (defun unix-get-locale-codeset ()
|
2904 | 2920 | _N"Get the codeset from the locale"
|
2905 | 2921 | (with-alien ((codeset (array c-call:char 512)))
|
... | ... | @@ -59,11 +59,12 @@ public domain. |
59 | 59 | * ~~#132~~ Ansi test `RENAME-FILE.1` no fails
|
60 | 60 | * ~~#134~~ Handle the case of `(expt complex complex-rational)`
|
61 | 61 | * ~~#136~~ `ensure-directories-exist` should return the given pathspec
|
62 | - * #139 `*default-external-format*` defaults to `:utf-8`
|
|
63 | - * #139 add alias for `:locale` external format
|
|
62 | + * #139 `*default-external-format*` defaults to `:utf-8`; add alias for `:locale` external format
|
|
63 | + * ~~#141~~ Disallow locales that are pathnames to a localedef file
|
|
64 | 64 | * ~~#142~~ `(random 0)` signals incorrect error
|
65 | 65 | * ~~#147~~ `stream-line-column` method missing for `fundamental-character-output-stream`
|
66 | 66 | * ~~#149~~ Call setlocale(3C) on startup
|
67 | + * ~~#155~~ Wrap help strings neatly
|
|
67 | 68 | * Other changes:
|
68 | 69 | * Improvements to the PCL implementation of CLOS:
|
69 | 70 | * Changes to building procedure:
|
... | ... | @@ -785,6 +785,19 @@ os_setlocale(void) |
785 | 785 | return result != NULL ? 0 : -1;
|
786 | 786 | }
|
787 | 787 | |
788 | +int
|
|
789 | +os_get_lc_messages(char *buf, int len)
|
|
790 | +{
|
|
791 | + char *locale = setlocale(LC_MESSAGES, NULL);
|
|
792 | + if (locale) {
|
|
793 | + strncpy(buf, locale, len - 1);
|
|
794 | + buf[len - 1] = '\0';
|
|
795 | + }
|
|
796 | + |
|
797 | + /* Return -1 if setlocale failed. */
|
|
798 | + return locale ? 0 : -1;
|
|
799 | +}
|
|
800 | + |
|
788 | 801 | void
|
789 | 802 | os_get_locale_codeset(char* codeset, int len)
|
790 | 803 | {
|
... | ... | @@ -794,4 +807,3 @@ os_get_locale_codeset(char* codeset, int len) |
794 | 807 | |
795 | 808 | strncpy(codeset, code, len);
|
796 | 809 | } |
797 | - |
... | ... | @@ -720,6 +720,30 @@ |
720 | 720 | (assert-equal (map 'list #'char-name string)
|
721 | 721 | (map 'list #'char-name (read-line s))))))
|
722 | 722 | |
723 | +(define-test issue.139-default-external-format-write-file
|
|
724 | + (:tag :issues)
|
|
725 | + ;; Test that opening a file for writing uses the default :utf8.
|
|
726 | + ;; First write something out to the file. Then read it back in
|
|
727 | + ;; using an explicit format of utf8 and verifying that we got the
|
|
728 | + ;; right contents.
|
|
729 | + (let ((string (concatenate 'string
|
|
730 | + ;; This is "hello" in Korean
|
|
731 | + '(#\Hangul_syllable_an
|
|
732 | + #\Hangul_Syllable_Nyeong
|
|
733 | + #\Hangul_Syllable_Ha
|
|
734 | + #\Hangul_Syllable_Se
|
|
735 | + #\Hangul_Syllable_Yo))))
|
|
736 | + (with-open-file (s (merge-pathnames "out-utf8.txt"
|
|
737 | + *test-path*)
|
|
738 | + :direction :output
|
|
739 | + :if-exists :supersede)
|
|
740 | + (write-line string s))
|
|
741 | + (with-open-file (s (merge-pathnames "out-utf8.txt"
|
|
742 | + *test-path*)
|
|
743 | + :direction :input
|
|
744 | + :external-format :utf-8)
|
|
745 | + (assert-equal (map 'list #'char-name string)
|
|
746 | + (map 'list #'char-name (read-line s))))))
|
|
723 | 747 | |
724 | 748 | (define-test issue.139-locale-external-format
|
725 | 749 | (:tag :issues)
|