Algorithms for moving the cursor to a date on a 12 month rotating calendar in Emacs

 ̄綄美尐妖づ 提交于 2019-12-01 15:57:59

问题


GOAL:  The goal of this thread is to create two (2) mathematical formulas to replace the long-hand solution by @lawlist in the function lawlist-calendar-cursor-to-visible-date (below).

                                                            STORY PROBLEM

There now exists a 12-month calendar in Emacs that scrolls forwards and backwards one month (or more) at a time. The function lawlist-calendar-cursor-to-visible-date is used to mark dates with overlays for designated events (e.g., birthdays, holidays, appointments, etc.); or, to simply move the cursor to a particular date. @lawlist has devised a solution by long-hand, which does not entirely use mathematical equations to calculate the cursor position for each of the 365 days that are displayed. It may be possible to create two (2) concise algorithms to replace the long-hand solution.

A working draft of the 12-month scrolling calendar (without the long-hand solution) may be found here:

     https://stackoverflow.com/a/21409154/2112489

LEGEND:

displayed-month (numbers 1 through 12) is the month that appears in the upper left-hand corner of the buffer, and this changes as the 12-month calendar is scrolled forwards or backwards.

The target month (numbers 1 through 12) is the month that we need to locate with assistance from the two mathematical formulas -- its location varies depending upon the date being marked (e.g., birthday, holiday, appointment), and depending upon the displayed-month in the upper left-hand corner of the buffer. The target month can be in any one of 12 possible positions. There are three (3) possible x axis coordinates (i.e., 6, 31, or 56). There are four (4) possible y axis coordinates (i.e., 0, 9, 18 or 27). [Citation to x / y coordinates: http://www.mathsisfun.com/data/cartesian-coordinates.html ]

A row is defined as 3 months horizontally.

A column is defined as 4 months vertically.

The first forumula must equal 0, 9, 18 or 27 depending upon whether the point is on row 1, 2, 3 or 4 -- i.e., from top to bottom.

The second forumula must equal 6, 31, or 56 depending upon whether the point is on column 1, 2 or 3 -- i.e., from left to right.

EXAMPLE:

  • If displayed-month is January (i.e., 1) and the target month is August (i.e., 8), then row equals 18 and column equals 31.

  • If displayed-month is February (i.e., 2) and the target month is August (i.e., 8), then row equals 18 and column equals 6.

  • If displayed-month is March (i.e., 3) and the target month is August (i.e., 8), then row equals 9 and column equals 56.

  • If displayed-month is April (i.e., 4) and target month is August (i.e., 8), then row equals 9 and column equals 31.

  • If displayed-month is May (i.e., 5) and the target month is August (i.e., 8), then row equals 9 and column equals 6.

The 12-month calendar looks like the following as the layout scrolls forward one month at a time:

;;  1 2 3
;;  4 5 6
;;  7 8 9
;;  10 11 12

;;  2 3 4
;;  5 6 7
;;  8 9 10
;;  11 12 1

;;  3 4 5
;;  6 7 8
;;  9 10 11
;;  12 1 2

;;  4 5 6
;;  7 8 9
;;  10 11 12
;;  1 2 3

;;  5 6 7
;;  8 9 10
;;  11 12 1
;;  2 3 4

;;  6 7 8
;;  9 10 11
;;  12 1 2
;;  3 4 5

;;  7 8 9
;;  10 11 12
;;  1 2 3
;;  4 5 6

;;  8 9 10
;;  11 12 1
;;  2 3 4
;;  5 6 7

;;  9 10 11
;;  12 1 2
;;  3 4 5
;;  6 7 8

;;  10 11 12
;;  1 2 3
;;  4 5 6
;;  7 8 9

;;  11 12 1
;;  2 3 4
;;  5 6 7
;;  8 9 10

;;  12 1 2
;;  3 4 5
;;  6 7 8
;;  9 10 11

The long-hand solution by @lawlist is as follows:

(defun lawlist-calendar-cursor-to-visible-date (date)
  "Move the cursor to DATE that is on the screen."
  (let* (
      (month (calendar-extract-month date))
      (day (calendar-extract-day date))
      (year (calendar-extract-year date))
      (first-of-month-weekday (calendar-day-of-week (list month 1 year))))
    (goto-line
      (+ 3
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        (cond
          ;;  1 2 3
          ;;  4 5 6
          ;;  7 8 9
          ;;  10 11 12
          ((and
              (eq displayed-month 1)
              (memq month `(1 2 3)))
            0)
          ((and
              (eq displayed-month 1)
              (memq month `(4 5 6)))
            9)
          ((and
              (eq displayed-month 1)
              (memq month `(7 8 9)))
            18)
          ((and
              (eq displayed-month 1)
              (memq month `(10 11 12)))
            27)
          ;;  2 3 4
          ;;  5 6 7
          ;;  8 9 10
          ;;  11 12 1
          ((and
              (eq displayed-month 2)
              (memq month `(2 3 4)))
            0)
          ((and
              (eq displayed-month 2)
              (memq month `(5 6 7)))
            9)
          ((and
              (eq displayed-month 2)
              (memq month `(8 9 10)))
            18)
          ((and
              (eq displayed-month 2)
              (memq month `(11 12 1)))
            27)
          ;;  3 4 5
          ;;  6 7 8
          ;;  9 10 11
          ;;  12 1 2
          ((and
              (eq displayed-month 3)
              (memq month `(3 4 5)))
            0)
          ((and
              (eq displayed-month 3)
              (memq month `(6 7 8)))
            9)
          ((and
              (eq displayed-month 3)
              (memq month `(9 10 11)))
            18)
          ((and
              (eq displayed-month 3)
              (memq month `(12 1 2)))
            27)
          ;;  4 5 6
          ;;  7 8 9
          ;;  10 11 12
          ;;  1 2 3
          ((and
              (eq displayed-month 4)
              (memq month `(4 5 6)))
            0)
          ((and
              (eq displayed-month 4)
              (memq month `(7 8 9)))
            9)
          ((and
              (eq displayed-month 4)
              (memq month `(10 11 12)))
            18)
          ((and
              (eq displayed-month 4)
              (memq month `(1 2 3)))
            27)
          ;;  5 6 7
          ;;  8 9 10
          ;;  11 12 1
          ;;  2 3 4
          ((and
              (eq displayed-month 5)
              (memq month `(5 6 7)))
            0)
          ((and
              (eq displayed-month 5)
              (memq month `(8 9 10)))
            9)
          ((and
              (eq displayed-month 5)
              (memq month `(11 12 1)))
            18)
          ((and
              (eq displayed-month 5)
              (memq month `(2 3 4)))
            27)
          ;;  6 7 8
          ;;  9 10 11
          ;;  12 1 2
          ;;  3 4 5
          ((and
              (eq displayed-month 6)
              (memq month `(6 7 8)))
            0)
          ((and
              (eq displayed-month 6)
              (memq month `(9 10 11)))
            9)
          ((and
              (eq displayed-month 6)
              (memq month `(12 1 2)))
            18)
          ((and
              (eq displayed-month 6)
              (memq month `(3 4 5)))
            27)
          ;;  7 8 9
          ;;  10 11 12
          ;;  1 2 3
          ;;  4 5 6
          ((and
              (eq displayed-month 7)
              (memq month `(7 8 9)))
            0)
          ((and
              (eq displayed-month 7)
              (memq month `(10 11 12)))
            9)
          ((and
              (eq displayed-month 7)
              (memq month `(1 2 3)))
            18)
          ((and
              (eq displayed-month 7)
              (memq month `(4 5 6)))
            27)
          ;;  8 9 10
          ;;  11 12 1
          ;;  2 3 4
          ;;  5 6 7
          ((and
              (eq displayed-month 8)
              (memq month `(8 9 10)))
            0)
          ((and
              (eq displayed-month 8)
              (memq month `(11 12 1)))
            9)
          ((and
              (eq displayed-month 8)
              (memq month `(2 3 4)))
            18)
          ((and
              (eq displayed-month 8)
              (memq month `(5 6 7)))
            27)
          ;;  9 10 11
          ;;  12 1 2
          ;;  3 4 5
          ;;  6 7 8
          ((and
              (eq displayed-month 9)
              (memq month `(9 10 11)))
            0)
          ((and
              (eq displayed-month 9)
              (memq month `(12 1 2)))
            9)
          ((and
              (eq displayed-month 9)
              (memq month `(3 4 5)))
            18)
          ((and
              (eq displayed-month 9)
              (memq month `(6 7 8)))
            27)
          ;;  10 11 12
          ;;  1 2 3
          ;;  4 5 6
          ;;  7 8 9
          ((and
              (eq displayed-month 10)
              (memq month `(10 11 12)))
            0)
          ((and
              (eq displayed-month 10)
              (memq month `(1 2 3)))
            9)
          ((and
              (eq displayed-month 10)
              (memq month `(4 5 6)))
            18)
          ((and
              (eq displayed-month 10)
              (memq month `(7 8 9)))
            27)
          ;;  11 12 1
          ;;  2 3 4
          ;;  5 6 7
          ;;  8 9 10
          ((and
              (eq displayed-month 11)
              (memq month `(11 12 1)))
            0)
          ((and
              (eq displayed-month 11)
              (memq month `(2 3 4)))
            9)
          ((and
              (eq displayed-month 11)
              (memq month `(5 6 7)))
            18)
          ((and
              (eq displayed-month 11)
              (memq month `(8 9 10)))
            27)
          ;;  12 1 2
          ;;  3 4 5
          ;;  6 7 8
          ;;  9 10 11
          ((and
              (eq displayed-month 12)
              (memq month `(12 1 2)))
            0)
          ((and
              (eq displayed-month 12)
              (memq month `(3 4 5)))
            9)
          ((and
              (eq displayed-month 12)
              (memq month `(6 7 8)))
            18)
          ((and
              (eq displayed-month 12)
              (memq month `(9 10 11)))
            27) )
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          (/ (+ day  -1
            (mod
              (- (calendar-day-of-week (list month 1 year)) calendar-week-start-day)
                7))
                  7)))
    (move-to-column
      (+ 
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        (cond
          ;;  1 2 3
          ;;  4 5 6
          ;;  7 8 9
          ;;  10 11 12
          ((and
              (eq displayed-month 1)
              (memq month `(1 4 7 10)))
            6)
          ((and
              (eq displayed-month 1)
              (memq month `(2 5 8 11)))
            31)
          ((and
              (eq displayed-month 1)
              (memq month `(3 6 9 12)))
            56)
          ;;  2 3 4
          ;;  5 6 7
          ;;  8 9 10
          ;;  11 12 1
          ((and
              (eq displayed-month 2)
              (memq month `(2 5 8 11)))
            6)
          ((and
              (eq displayed-month 2)
              (memq month `(3 6 9 12)))
            31)
          ((and
              (eq displayed-month 2)
              (memq month `(4 7 10 1)))
            56)
          ;;  3 4 5
          ;;  6 7 8
          ;;  9 10 11
          ;;  12 1 2
          ((and
              (eq displayed-month 3)
              (memq month `(3 6 9 12)))
            6)
          ((and
              (eq displayed-month 3)
              (memq month `(4 7 10 1)))
            31)
          ((and
              (eq displayed-month 3)
              (memq month `(5 8 11 2)))
            56)
          ;;  4 5 6
          ;;  7 8 9
          ;;  10 11 12
          ;;  1 2 3
          ((and
              (eq displayed-month 4)
              (memq month `(4 7 10 1)))
            6)
          ((and
              (eq displayed-month 4)
              (memq month `(5 8 11 2)))
            31)
          ((and
              (eq displayed-month 4)
              (memq month `(6 9 12 3)))
            56)
          ;;  5 6 7
          ;;  8 9 10
          ;;  11 12 1
          ;;  2 3 4
          ((and
              (eq displayed-month 5)
              (memq month `(5 8 11 2)))
            6)
          ((and
              (eq displayed-month 5)
              (memq month `(6 9 12 3)))
            31)
          ((and
              (eq displayed-month 5)
              (memq month `(7 10 1 4)))
            56)
          ;;  6 7 8
          ;;  9 10 11
          ;;  12 1 2
          ;;  3 4 5
          ((and
              (eq displayed-month 6)
              (memq month `(6 9 12 3)))
            6)
          ((and
              (eq displayed-month 6)
              (memq month `(7 10 1 4)))
            31)
          ((and
              (eq displayed-month 6)
              (memq month `(8 11 2 5)))
            56)
          ;;  7 8 9
          ;;  10 11 12
          ;;  1 2 3
          ;;  4 5 6
          ((and
              (eq displayed-month 7)
              (memq month `(7 10 1 4)))
            6)
          ((and
              (eq displayed-month 7)
              (memq month `(8 11 2 5)))
            31)
          ((and
              (eq displayed-month 7)
              (memq month `(9 12 3 6)))
            56)
          ;;  8 9 10
          ;;  11 12 1
          ;;  2 3 4
          ;;  5 6 7
          ((and
              (eq displayed-month 8)
              (memq month `(8 11 2 5)))
            6)
          ((and
              (eq displayed-month 8)
              (memq month `(9 12 3 6)))
            31)
          ((and
              (eq displayed-month 8)
              (memq month `(10 1 4 7)))
            56)
          ;;  9 10 11
          ;;  12 1 2
          ;;  3 4 5
          ;;  6 7 8
          ((and
              (eq displayed-month 9)
              (memq month `(9 12 3 6)))
            6)
          ((and
              (eq displayed-month 9)
              (memq month `(10 1 4 7)))
            31)
          ((and
              (eq displayed-month 9)
              (memq month `(11 2 5 8)))
            56)
          ;;  10 11 12
          ;;  1 2 3
          ;;  4 5 6
          ;;  7 8 9
          ((and
              (eq displayed-month 10)
              (memq month `(10 1 4 7)))
            6)
          ((and
              (eq displayed-month 10)
              (memq month `(11 2 5 8)))
            31)
          ((and
              (eq displayed-month 10)
              (memq month `(12 3 6 9)))
            56)
          ;;  11 12 1
          ;;  2 3 4
          ;;  5 6 7
          ;;  8 9 10
          ((and
              (eq displayed-month 11)
              (memq month `(11 2 5 8)))
            6)
          ((and
              (eq displayed-month 11)
              (memq month `(12 3 6 9)))
            31)
          ((and
              (eq displayed-month 11)
              (memq month `(1 4 7 10)))
            56)
          ;;  12 1 2
          ;;  3 4 5
          ;;  6 7 8
          ;;  9 10 11
          ((and
              (eq displayed-month 12)
              (memq month `(12 3 6 9)))
            6)
          ((and
              (eq displayed-month 12)
              (memq month `(1 4 7 10)))
            31)
          ((and
              (eq displayed-month 12)
              (memq month `(2 5 8 11)))
            56) )
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          (* 3 (mod
            (- (calendar-day-of-week date) calendar-week-start-day)
              7))))))

回答1:


I must be missing something because it looks like the formulas are as simple as (pseudocode):

first  = 9 * ( rows - 1 ) 
second = 6 + 25 * ( cols - 1 )

based on your edit, you can calculate the rows and cols to move with:

if target > display
   difference = target - display
else 
   difference = 12 + target - display
 rows = difference / 3 
 cols = difference % 3
 rowmove = 9 * rows 
 colmove = 6 + 25 * cols

And then use the formula above.

My attempt at elisp:

(let difference (if (>= target-month display-month) 
                      (- target-month display-month) 
                    (- (+ target-month 12) display-month)))
(let rows (/ difference 3))
(let cols (% difference 3))
(let rowmove (* 9 rows))   
(let colmove (+ 6 (* 25 cols)))


来源:https://stackoverflow.com/questions/21642010/algorithms-for-moving-the-cursor-to-a-date-on-a-12-month-rotating-calendar-in-em

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!