2010-11-29 32 views
2

J'essaie d'implémenter les termes solaires dans mon .emacs afin que mes "vacances" affichent l'heure à laquelle la longitude solaire croise chaque multiple de 15 degrés. Voici le snipplet pertinent.Pourquoi Emacs se plaint de void-variable display-year dans mon fichier .emacs?

(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)) 

Cependant, emacs (version 23.2-r2 sur Gentoo) se plaint affiché année étant une variable vide au démarrage, et d'essayer de générer le calendrier avec Mx calendrier RET ne contribue pas non plus . Une idée de comment je peux réparer ça? (Certainement pas avec définir année-affichée dans mon .emacs puisque cela vider définitivement tout le reste ...)

+0

Avez-vous eu besoin d'un calendrier et le charger avant d'exécuter cette fonction? –

Répondre

1

le calcul doit être différé jusqu'à ce que displayed-year est disponible, ce qui peut être obtenue en remplaçant le dernière expression dans votre pâte avec ces deux:

(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)) 
+0

Merci. Cela fonctionne parfaitement. –

3

Parce que vous n'avez pas lié le symbole displayed-year à une valeur. Consultez la dernière ligne du let* obligatoire pour astronextdate:

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

Ce symbole est pas lié à une valeur, de sorte que vous obtenez une erreur variable vide. La variable est définie dans la bibliothèque calendar qui a la documentation:

;; 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 

, il semble donc que vous avez juste besoin d'ajouter:

(require 'calendar) 

pour forcer Emacs à charger le package qui définit la variable avant main.

Cela dit, il sera défini, mais pas encore lié. Vous devez changer votre code à assumer pas lié statiquement solar-terms-holidays, mais devrait en faire une fonction qui calcule les sur demande, parce que le displayed-year est uniquement lié lorsque le calendrier est en fait en cours d'exécution ...

Ainsi, une solution possible est de faire ce qui suit, envelopper votre setq comme suit pour assurer que les variables sont liées comme vous les attendez d'être:

(save-window-excursion 
    (calendar) 
    (setq solar-terms-holidays 
     ....) 
    (calendar-exit)) 
+1

Vous devez faire plus que simplement '(require 'calendar)', vous devez réellement lancer la fonction 'calendar'. –

+0

@GarethRees Yah, j'ajoutais cela en tapant votre commentaire. :) Et nous avons tous les deux édité la question en même temps. Je suppose que nous sommes en phase. –

+0

J'ai oublié d'ajouter --- J'ai (exige 'calendrier) au début de mon fichier .emacs, mais emacs se plaint encore. –