summaryrefslogtreecommitdiffstats
path: root/emacs.d/lisp/rudel/rudel-compat.el
blob: 630496c54cd6190be62de9bcea8fb39cfb22c45e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
;;; rudel-compat.el --- Compatibility code for Rudel
;;
;; Copyright (C) 2009 Jan Moringen
;; Copyright (C) 2009 Phil Hagelberg
;;
;; Author: Jan Moringen <scymtym@users.sourceforge.net>
;;         Phil Hagelberg <phil@enigma>
;; Keywords: rudel, compatibility
;; X-RCS: $Id:$
;;
;; This file is part of Rudel.
;;
;; Rudel is free software: you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; Rudel is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with Rudel. If not, see <http://www.gnu.org/licenses>.


;;; Commentary:
;;
;; This file contains compatibility code required to make Rudel work
;; with different versions of Emacs.


;;; History:
;;
;; 0.1 - Initial revision


;;; Code:
;;

(unless (fboundp 'read-color)
  (defun read-color (prompt &rest ignored)
    "Poor man's read color without completion.
You have to take care to only enter valid color names."
    (read-string prompt)))


;;; Spinner Progress Reporter
;;

(unless (functionp 'progress-reporter-spin)
  (defvar progress-spinner-values ["-" "\\" "|" "/"])

  (defsubst progress-reporter-update (reporter &optional value)
  "Report progress of an operation in the echo area.

The first parameter, REPORTER, should be the result of a call to
`make-progress-reporter'. For reporters for which the max value
is known, the second argument determines the actual progress of
operation; it must be between MIN-VALUE and MAX-VALUE as passed
to `make-progress-reporter'.

However, if the change since last echo area update is too small
or not enough time has passed, then do nothing (see
`make-progress-reporter' for details).

In this case, this function is very inexpensive, you need not
care how often you call it."
  (if (progress-reporter-spinner-p reporter)
      (progress-reporter-spin reporter)
    (when (>= value (car reporter))
      (progress-reporter-do-update reporter value))))

    (defun make-progress-reporter (message &optional min-value max-value
                                           current-value min-change min-time)
      "Return progress reporter object to be used with `progress-reporter-update'.

MESSAGE is shown in the echo area.  When at least 1% of operation
is complete, the exact percentage will be appended to the
MESSAGE.  When you call `progress-reporter-done', word \"done\"
is printed after the MESSAGE.  You can change MESSAGE of an
existing progress reporter with `progress-reporter-force-update'.

If provided, MIN-VALUE and MAX-VALUE designate starting (0%
complete) and final (100% complete) states of operation.  The
latter should be larger; if this is not the case, then simply
negate all values.  Optional CURRENT-VALUE specifies the progress
by the moment you call this function.  You should omit it or set
it to nil in most cases since it defaults to MIN-VALUE.

Optional MIN-CHANGE determines the minimal change in percents to
report (default is 1%.)  Optional MIN-TIME specifies the minimal
time before echo area updates (default is 0.2 seconds.)  If
`float-time' function is not present, then time is not tracked
at all.  If OS is not capable of measuring fractions of seconds,
then this parameter is effectively rounded up.

If MIN-VALUE and MAX-VALUE are unknown, they may be omitted to
return a \"pulsing\" progress reporter."
      (unless min-time
        (setq min-time 0.2))
      (let ((reporter
             (cons min-value ;; Force a call to `message' now
                   (vector (if (and (fboundp 'float-time)
                                    (>= min-time 0.02))
                               (float-time) nil)
                           (or min-value 0)
                           max-value
                           message
                           (if min-change (max (min min-change 50) 1) 1)
                           min-time))))
        (progress-reporter-update reporter (or current-value min-value))
        reporter))

    (defun progress-reporter-force-update (reporter &optional value new-message)
        "Report progress of an operation in the echo area unconditionally.

First two parameters are the same as for
`progress-reporter-update'.  Optional NEW-MESSAGE allows you to
change the displayed message."
        (let ((parameters (cdr reporter)))
          (when new-message
            (aset parameters 3 new-message))
          (when (aref parameters 0)
            (aset parameters 0 (float-time)))
          (if (progress-reporter-spinner-p reporter)
              (progress-reporter-spin reporter)
            (progress-reporter-do-update reporter value))))

      (defun progress-reporter-spinner-p (reporter)
        "Return t if REPORTER has an unknown max value."
        (null (aref (cdr reporter) 2)))

      (defun progress-reporter-spin (reporter)
        "Advance indicator of spinning REPORTER."
        (let* ((parameters (cdr reporter))
               (index      (+ (aref parameters 1) 1)))
          (aset parameters 1 index)
          (let ((message-log-max nil)) ; No logging
            (message "%s %s"
                     (aref progress-spinner-values (mod index 4))
                     (aref parameters 3))))))

(unless (functionp 'string-match-p)
  (defsubst string-match-p (regexp string &optional start)
    "Same as `string-match' except this function does not change the match data"
    (let ((inhibit-changing-match-data t))
      (string-match regexp string start))))

(defun rudel-get-coding-system (name)
  (if (functionp 'coding-system-from-name)
      (coding-system-from-name name)
    ;; May need to try a little harder here for Emacs 22 depending on
    ;; what kind of encoding names are given us.
    (intern name)))

(provide 'rudel-compat)
;;; rudel-compat.el ends here