2

我正在尝试在我的“假期”中实施节气,.emacs因此我的“假期”将显示太阳经度穿过每个 15 度的倍数的时间。这是相关的片段。

(defun next-solar-term-date (d)
  (solar-date-next-longitude d 15))

(defconst solar-term-names
  ["moderate cold" "severe cold" "spring commerces"
   "rain water" "insects awaken" "vernal equinox"
   "Ching Ming" "corn rain" "summer commerces"
   "corn forms" "corn on ear" "summer solstice"
   "minor heat" "great heat" "autumn commerces"
   "end of heat" "white dew" "autumnal equinox"
   "cold dew" "frost" "winter commerces"
   "light snow" "heavy snow" "winter solstice"])

(setq solar-terms-holidays
      (let* ((k 0) (mylist nil))
        (dotimes (k 4);k=season
          (let* ((j 0))
            (dotimes (j 5);no equinoxes/solstices --- use solar for them
              (let* ((i (+ j (* 6 k)))
                     (month (+ 1 (/ i 2)))
                     (astronextdate (next-solar-term-date
                                     (calendar-astro-from-absolute
                                      (+ (* 15 i)
                                         (calendar-absolute-from-gregorian
                                          (list 1 1 displayed-year))))))
                     (s (aref solar-term-names i))
                     (absnextdate (calendar-absolute-from-astro
                                   astronextdate))
                     (gregnextdate (calendar-gregorian-from-absolute
                                    (floor absnextdate)))
                     (compt (* 24 (- absnextdate (floor absnextdate))))
                     (str (concat s " "
                                  (solar-time-string
                                   compt (if (dst-in-effect absnextdate)
                                             calendar-daylight-time-zone-name
                                           calendar-standard-time-zone-name))))
                     (d (extract-calendar-day gregnextdate)))
                (setq mylist (append mylist
                                     (list
                                      (list 'holiday-fixed month d str))))))))
        mylist))

但是,emacs(Gentoo 上的版本 23.2-r2)抱怨显示年份在启动时是一个无效变量,并且尝试生成日历M-x calendar RET也无济于事。知道我该如何解决吗?(当然不是在我定义显示年份,.emacs因为这肯定会搞砸其他一切......)

4

2 回答 2

3

因为您尚未将符号绑定displayed-year到值。查看let*绑定中的最后一行astronextdate

                                      (list 1 1 displayed-year))))))

该符号未绑定到任何值,因此您会收到 void variable 错误。该变量在calendar具有文档的库中定义:

;; A note on free variables:

;; The calendar passes around a few dynamically bound variables, which
;; unfortunately have rather common names.  They are meant to be
;; available for external functions, so the names can't be changed.

;; displayed-month, displayed-year: bound in calendar-generate, the
;;   central month of the 3 month calendar window

所以,看起来你只需要添加:

(require 'calendar)

强制 Emacs 加载预先定义变量的包。

也就是说,它将被定义,但尚未绑定。您应该将代码更改为不假定静态绑定solar-terms-holidays,而应将其转换为按需计算的函数,因为displayed-year仅在日历实际运行时才绑定...

因此,一种可能的解决方案是执行以下操作,按如下方式包装您setq的变量,以确保变量像您期望的那样绑定:

(save-window-excursion
  (calendar)
  (setq solar-terms-holidays
        ....)
  (calendar-exit))
于 2010-11-29T18:25:47.787 回答
1

计算需要推迟到displayed-year可用,这可以通过用这两个替换粘贴中的最后一个表达式来实现:

(defun solar-term (i month)
  (let* ((astronextdate (next-solar-term-date
                         (calendar-astro-from-absolute
                          (+ (* 15 i)
                             (calendar-absolute-from-gregorian
                              (list 1 1 displayed-year))))))
         (s (aref solar-term-names i))
         (absnextdate (calendar-absolute-from-astro
                       astronextdate))
         (gregnextdate (calendar-gregorian-from-absolute
                        (floor absnextdate)))
         (compt (* 24 (- absnextdate (floor absnextdate))))
         (str (concat s " "
                      (solar-time-string
                       compt (if (dst-in-effect absnextdate)
                                 calendar-daylight-time-zone-name
                               calendar-standard-time-zone-name))))
         (d (extract-calendar-day gregnextdate)))
    (holiday-fixed month d str)))

(setq solar-terms-holidays
      (let* ((mylist nil))
        (dotimes (k 4)    ;k=season
          (dotimes (j 5)  ;no equinoxes/solstices --- use solar for them
            (let* ((i (+ j (* 6 k)))
                   (month (+ 1 (/ i 2))))
              (push `(solar-term ,i ,month) mylist))))
        mylist))
于 2010-11-30T12:46:21.003 回答