Compare commits

...

6 Commits

View File

@ -106,8 +106,10 @@ end date of the timeline."
(define-key map "k" #'timeline-tools-kill-line)
(define-key map (kbd "C-n") #'timeline-tools-next-line)
(define-key map "n" #'timeline-tools-next-line)
(define-key map "N" #'timeline-tools-swap-line-with-next)
(define-key map (kbd "C-p") #'timeline-tools-previous-line)
(define-key map "p" #'timeline-tools-previous-line)
(define-key map "P" #'timeline-tools-swap-line-with-previous)
(define-key map "o" #'delete-other-windows)
map))
@ -468,7 +470,8 @@ archives."
(defun timeline-tools-redraw-timeline (&optional force)
"Redraw timeline of current buffer.
If `force' is non-nil, reparse the timeline using
If FORCE is non-nil, reparse the timeline using
`timeline-tools-timeline' within the time span given by the
current values of the relevant buffer local variables."
(interactive)
@ -518,38 +521,68 @@ current values of the relevant buffer local variables."
(timeline-tools-format-entry-time line 'end)
(timeline-tools-entry-duration line)
(timeline-tools-entry-headline line))
'marker (timeline-tools-entry-marker line)
'entry line))))
(insert "|--|\n")
(org-table-align)
(goto-char (point-min))
(timeline-tools-next-line))))
(defun timeline-tools-next-line ()
"Move point to next line in timetable, if possible."
(interactive)
(unless (eq major-mode 'timeline-tools-mode)
(user-error "Not in Timeline buffer"))
(defun timeline-tools--get-entry-from-point (&optional noerror)
"Return timeline entry of point when in timeline buffer.
Errors out if there is no entry on the current line, unless
NOERROR is non-nil; in that case, return nil when no text
property could be found (note that this can also happen if point
is outside of the current table)."
(unless (derived-mode-p 'timeline-tools-mode))
(save-mark-and-excursion
(if (not (org-at-table-p))
(if noerror nil (user-error "Not in table"))
(beginning-of-line)
(let ((point (point)))
(when (looking-at "^| ")
(forward-line))
(unless (re-search-forward "^| " nil 'no-error)
(if (not (looking-at "^| "))
(if noerror nil (user-error "Not on valid row in timeline"))
(org-table-next-field)
(if-let ((entry (get-text-property (point) 'entry)))
entry
(if noerror nil (user-error "Not on valid row in timeline")))))))
(defun timeline-tools-next-line ()
"Move point to next line in timetable, if possible.
Otherwise don't move point and error out."
(interactive)
(unless (derived-mode-p 'timeline-tools-mode)
(user-error "Not in Timeline buffer"))
(let ((point (point))
found)
(end-of-line)
(while (and (setq found (re-search-forward "^| " nil t))
(not (timeline-tools--get-entry-from-point 'noerror))))
;; Check whether we've found something when leaving the while-loop; if not,
;; go back and error out, as promised in the docstring.
(unless found
(goto-char point)
(user-error "No next line"))
(beginning-of-line)))
(user-error "No next line")))
(beginning-of-line))
(defun timeline-tools-previous-line ()
"Move point to previous line in timetable, if possible."
"Move point to previous line in timetable, if possible.
Otherwise don't move point and error out."
(interactive)
(unless (eq major-mode 'timeline-tools-mode)
(user-error "Not in Timeline buffer"))
(beginning-of-line)
(let ((point (point)))
(unless (re-search-backward "^| " nil 'no-error)
(let ((point (point))
found)
(while (and (setq found (re-search-backward "^| " nil t))
(not (timeline-tools--get-entry-from-point 'noerror))))
;; Check whether we've found something when leaving the while-loop; if not,
;; go back and error out, as promised in the docstring.
(unless found
(goto-char point)
(user-error "No previous line"))
(beginning-of-line)))
(user-error "No previous line")))
(beginning-of-line))
(defun timeline-tools--get-timeline-from-buffer ()
"Extract current timeline from buffer and return it.
@ -582,6 +615,9 @@ Updates category properties before constructing the new timeline."
(interactive)
(if (not (eq major-mode 'timeline-tools-mode))
(user-error "Not in Timeline buffer")
;; CAVEAT: this does not work properly when daylight time saving occured.
;; In that case, jump directly to the day you want to display. This is not
;; going to be fixed.
(setq-local timeline-tools--current-time-start (+ 86400 timeline-tools--current-time-start))
(setq-local timeline-tools--current-time-end (+ 86400 timeline-tools--current-time-end))
(timeline-tools-redraw-timeline 'force)))
@ -602,12 +638,7 @@ Updates category properties before constructing the new timeline."
(interactive)
(unless (eq major-mode 'timeline-tools-mode)
(user-error "Not in Timeline buffer"))
(let ((marker (save-mark-and-excursion
(beginning-of-line)
(org-table-next-field)
(get-text-property (point) 'marker))))
(unless marker
(user-error "Not on headline to jump to"))
(let ((marker (timeline-tools-entry-marker (timeline-tools--get-entry-from-point))))
(switch-to-buffer (marker-buffer marker))
(goto-char marker)
(org-reveal)))
@ -617,26 +648,92 @@ Updates category properties before constructing the new timeline."
(interactive)
(unless (eq major-mode 'timeline-tools-mode)
(user-error "Not in Timeline buffer"))
(save-mark-and-excursion
;; get actual entry from headline of line
(beginning-of-line)
(unless (looking-at "^| ")
(user-error "Not in table"))
(org-table-next-field)
(let ((entry (get-text-property (point) 'entry)))
(unless entry
(user-error "Not on valid row in timeline"))
(kill-line)))
;; the call to `erase-buffer in `timeline-tools-redraw-timeline somehow
;; makes `save-mark-and-excursion meaningless; thus we save the number of the
;; If there's an entry on the current line, delete it and redraw; the call to
;; `erase-buffer in `timeline-tools-redraw-timeline somehow makes
;; `save-mark-and-excursion meaningless; thus we save the number of the
;; current line by ourselves
(if (timeline-tools--get-entry-from-point) ; barfs if there's no entry
(kill-line))
(let ((linenum (line-number-at-pos (point))))
(timeline-tools-redraw-timeline)
(goto-char (point-min))
(forward-line (1- linenum))))
(defun timeline-tools-swap-line-with-next ()
"Swap the current line with the next line in current timeline.
Durations of the entries are kept, the start and end times are
changed accordingly."
(interactive)
(unless (derived-mode-p 'timeline-tools-mode)
(user-error "Not in Timeline buffer"))
;; The idea is to swap the two entries attached as text properties to the rows
;; and update the start end end times accordingly, and then redraw.
(let (pos-entry-1 pos-entry-2 entry-1 entry-2)
(save-mark-and-excursion
(setq entry-1 (timeline-tools--get-entry-from-point)
pos-entry-1 (point))
(timeline-tools-next-line)
(setq entry-2 (timeline-tools--get-entry-from-point)
pos-entry-2 (point)))
;; Let's create new entries and overwrite the old ones.
(let ((s1 (timeline-tools-entry-start-time entry-1))
(m1 (timeline-tools-entry-marker entry-1))
(s2 (timeline-tools-entry-start-time entry-2))
(e2 (timeline-tools-entry-end-time entry-2))
(m2 (timeline-tools-entry-marker entry-2))
entry-1-new entry-2-new)
(setq entry-1-new (timeline-tools-make-entry s1 (+ s1 (- e2 s2)) m2)
entry-2-new (timeline-tools-make-entry (+ s1 (- e2 s2)) e2 m1))
(save-mark-and-excursion
(goto-char pos-entry-1)
(put-text-property (line-beginning-position)
(line-end-position)
'entry entry-1-new)
(goto-char pos-entry-2)
(put-text-property (line-beginning-position)
(line-end-position)
'entry entry-2-new))
(timeline-tools-redraw-timeline)
;; Stay on line we were previously, by searching for an entry that has
;; the same starting time as `entry-2-new', going there.
;; XXX: problem is that entries may get transformed by functions from
;; `timeline-tools-transform-timeline', so this approach is not correct
;; in general.
(text-property-search-forward 'entry
(timeline-tools-entry-start-time entry-2-new)
#'(lambda (x y)
(equal x (timeline-tools-entry-start-time y)))))))
(defun timeline-tools-swap-line-with-previous ()
"Swap the current line with the previous line in current timeline.
See `timeline-tools-swap-line-with-next' for more details."
(interactive)
(unless (derived-mode-p 'timeline-tools-mode)
(user-error "Not in Timeline buffer"))
;; Go to the previous line and swap those.
(timeline-tools-previous-line)
(timeline-tools-swap-line-with-next)
(timeline-tools-previous-line))
;;; Manipulating Clocklines
;;; Manipulating Clocklines in Org Files
;; XXX: All this needs some autoloadable frontend