rng-util.el 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. ;;; rng-util.el --- utility functions for RELAX NG library
  2. ;; Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc.
  3. ;; Author: James Clark
  4. ;; Keywords: XML, RelaxNG
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. (defun rng-make-datatypes-uri (uri)
  19. (if (string-equal uri "")
  20. ;; The spec doesn't say to do this, but it's perfectly conformant
  21. ;; and better than using nil, I think.
  22. 'http://relaxng.org/ns/structure/1.0
  23. (intern uri)))
  24. (defconst rng-xsd-datatypes-uri
  25. (rng-make-datatypes-uri "http://www.w3.org/2001/XMLSchema-datatypes"))
  26. (defconst rng-builtin-datatypes-uri (rng-make-datatypes-uri ""))
  27. (defun rng-uniquify-eq (list)
  28. "Destructively remove `eq' duplicates from LIST."
  29. (and list
  30. (let ((head list))
  31. (while (cdr head)
  32. (if (eq (car head) (cadr head))
  33. (setcdr head (cddr head)))
  34. (setq head (cdr head)))
  35. list)))
  36. (defun rng-uniquify-equal (list)
  37. "Destructively remove `equal' duplicates from LIST."
  38. (and list
  39. (let ((head list))
  40. (while (cdr head)
  41. (if (equal (car head) (cadr head))
  42. (setcdr head (cddr head)))
  43. (setq head (cdr head)))
  44. list)))
  45. (defun rng-blank-p (str) (string-match "\\`[ \t\n\r]*\\'" str))
  46. (defun rng-substq (new old list)
  47. "Replace first member of LIST (if any) that is `eq' to OLD by NEW.
  48. LIST is not modified."
  49. (cond ((null list) nil)
  50. ((eq (car list) old)
  51. (cons new (cdr list)))
  52. (t
  53. (let ((tail (cons (car list)
  54. nil))
  55. (rest (cdr list)))
  56. (setq list tail)
  57. (while rest
  58. (let ((item (car rest)))
  59. (setq rest (cdr rest))
  60. (cond ((eq item old)
  61. (setcdr tail
  62. (cons new rest))
  63. (setq rest nil))
  64. (t
  65. (setq tail
  66. (setcdr tail
  67. (cons item nil))))))))
  68. list)))
  69. (defun rng-complete-before-point (start table prompt &optional predicate hist)
  70. "Complete text between START and point.
  71. Replaces the text between START and point with a string chosen using a
  72. completion table and, when needed, input read from the user with the
  73. minibuffer.
  74. Returns the new string if either a complete and unique completion was
  75. determined automatically or input was read from the user. Otherwise,
  76. returns nil.
  77. TABLE is an alist, a symbol bound to a function or an obarray as with
  78. the function `completing-read'.
  79. PROMPT is the string to prompt with if user input is needed.
  80. PREDICATE is nil or a function as with `completing-read'.
  81. HIST, if non-nil, specifies a history list as with `completing-read'."
  82. (let* ((orig (buffer-substring-no-properties start (point)))
  83. (completion (try-completion orig table predicate)))
  84. (cond ((not completion)
  85. (if (string= orig "")
  86. (message "No completions available")
  87. (message "No completion for %s" (rng-quote-string orig)))
  88. (ding)
  89. nil)
  90. ((eq completion t) orig)
  91. ((not (string= completion orig))
  92. (delete-region start (point))
  93. (insert completion)
  94. (cond ((not (rng-completion-exact-p completion table predicate))
  95. (message "Incomplete")
  96. nil)
  97. ((eq (try-completion completion table predicate) t)
  98. completion)
  99. (t
  100. (message "Complete but not unique")
  101. nil)))
  102. (t
  103. (setq completion
  104. (let ((saved-minibuffer-setup-hook
  105. (default-value 'minibuffer-setup-hook)))
  106. (add-hook 'minibuffer-setup-hook
  107. 'minibuffer-completion-help
  108. t)
  109. (unwind-protect
  110. (completing-read prompt
  111. table
  112. predicate
  113. nil
  114. orig
  115. hist)
  116. (setq-default minibuffer-setup-hook
  117. saved-minibuffer-setup-hook))))
  118. (delete-region start (point))
  119. (insert completion)
  120. completion))))
  121. (defun rng-completion-exact-p (string table predicate)
  122. (cond ((symbolp table)
  123. (funcall table string predicate 'lambda))
  124. ((vectorp table)
  125. (intern-soft string table))
  126. (t (assoc string table))))
  127. (defun rng-quote-string (s)
  128. (concat "\"" s "\""))
  129. (defun rng-escape-string (s)
  130. (replace-regexp-in-string "[&\"<>]"
  131. (lambda (match)
  132. (cdr (assoc match
  133. '(("&" . "&amp;")
  134. ("\"" . "&quot;")
  135. (">" . "&gt;")
  136. ("<" . "&lt;")))))
  137. s
  138. t))
  139. (defun rng-collapse-space (string)
  140. (setq string
  141. (replace-regexp-in-string "[ \t\r\n]+" " " string t t))
  142. (when (string-match "\\` " string)
  143. (setq string (substring string 1)))
  144. (when (string-match " \\'" string)
  145. (setq string (substring string 0 -1)))
  146. string)
  147. (provide 'rng-util)
  148. ;;; rng-util.el ends here