kiwanami / emacs-calfw

A calendar framework for Emacs
1.17k stars 100 forks source link

Only show Org items with one TODO state (WAITING, DONE, etc.) #69

Closed mankoff closed 9 years ago

mankoff commented 9 years ago

Is it possible to have calfw only show items that match a TODO state? For example, only TODO, or WAITING, or DONE items, but not all items, from the Org agenda files?

mankoff commented 9 years ago

I've based my attempts at this off of #18 and @konubinix (see https://github.com/kiwanami/emacs-calfw/issues/18#issuecomment-9134716), but without success. I currently have this, which I hope would only show EVENT items, but all items are shown:

(defun konix/cfw:open-org-calendar (&rest args)
  (interactive)
  (let (
        (org-agenda-skip-function '(org-agenda-skip-entry-if  'nottodo '("EVENT")))
        )
    (cfw:open-org-calendar)
    )
  ;; set the org variables to remember
  (set (make-variable-buffer-local 'org-agenda-skip-function) org-agenda-skip-function)
  )

(konix/cfw:open-org-calendar)
skyer9 commented 9 years ago

currently there is variable org-agenda-entry-types.

mankoff commented 9 years ago

That works a bit better. If I have this code:

(defun konix/cfw:open-org-calendar (&rest args)
  (interactive)
  (let (
        (org-agenda-entry-types '(:timestamp))
        )
    (cfw:open-org-calendar)
    )
  ;; set the org variables to remember
  (set (make-variable-buffer-local 'org-agenda-entry-types) org-agenda-entry-types)
  )

(konix/cfw:open-org-calendar)

Then the initial view doesn't show SCHEDULED or DEADLINE items. Getting closer.

But when I change month view with >, the settings revert to default and everything is shown. It appears my make-variable-buffer-local command is not correct.

kiwanami commented 9 years ago

Hi @mankoff How about cfw:org-agenda-schedule-args?

(setq cfw:org-agenda-schedule-args '(:timestamp))
mankoff commented 9 years ago

Yes, that appears to work well. Thank you!

kiwanami commented 9 years ago

Thank you for your confirmation. I'd add some document for cfw:org-agenda-schedule-args.

Asalle commented 5 years ago

How is this filtering out enties with TODO state?

kafu16 commented 1 year ago

How is this filtering out enties with TODO state?

I would also be really interested in how to only display certain todo-items (e.g. WAITING or DONE). When having many headlines for a certain day, due to limited space in the "boxes" for the days not all headlines can be displayed. So only displaying items with certain todo-keywords would solve this problem.

lawlist commented 1 year ago

The underlying code should adhere to those functions / variables that are examined by the org-agenda-skip function ... Therefore, let-binding the applicable variables with the desired values when calling cfw:open-org-calendar should suffice. See: https://orgmode.org/manual/Special-Agenda-Views.html

NOTE: cfw:org-agenda-schedule-args has a default value of nil, in which case calfw will defer to org-agenda-entry-types. This is a list. The available elements of that list are as follows: :todo, :timestamp, :sexp, :scheduled, :scheduled*, :closed, :deadline, and :deadline*.

kafu16 commented 1 year ago

Thank you for this hint! I read the manual but I didn't figure it out. I don't know how to adapt org-agenda-entry-types. I got that I can do something like (setq org-agenda-entry-types '(:deadline)) but how to adapt that to filter only e.g. items with WAITING as todo keyword. Can you give a short example? And maybe also how to embed that in a let-binding in order to only apply this to calfw and not to the agenda.

lawlist commented 1 year ago

If the task/event contains the keyword WAITING, a decision needs to be made by you regarding what type of entry type it is. E.g., does it contain a deadline or a scheduled timestamp?, etc. If the task/event contains a deadline and the desired effect is for the calendar to show those tasks/events with a deadline timestamp, then (setq org-agenda-entry-types '(:deadline)) is fine. Insofar as the org-agenda-skip-function, the manual provides several possibilities, such as using a regex, or a particular keyword. In the following example, I chose to to filter out those tasks/events with the keywords PROJ and WAITING, and org-agenda-entry-types is let-bound to :deadline only. If the task/event containing the keyword WAITING or PROJ did not contain a deadline timestamp, then there would be no need to filter it out using the skip function.

(let ((org-agenda-skip-function
         '(org-agenda-skip-entry-if 'todo '("PROJ" "WAITING")))
      (org-agenda-entry-types '(:deadline)))
  (cfw:open-org-calendar))
kafu16 commented 1 year ago

Thank you! I put this snippet in my init.el (when I put it in calfw.el the fixes from https://github.com/kiwanami/emacs-calfw/issues/152 get reversed).

Somehow the behavior does not change. When I set

(setq org-agenda-skip-function
         '(org-agenda-skip-entry-if 'todo '("PROJ" "WAITING")))

the changes apply, but also for the normal agenda view. (I do not use scheduled timestamps). So somehow the let-binding seems not to work?

lawlist commented 1 year ago

The doc-string for org-agenda-skip-function recommends to never use setq. It is meant to be let-bound (temporary basis for the duration of a particular search). There are some more hints in the doc-string regarding global and temporary settings. Type C-h v aka M-x describe-variable after the org library has been loaded.

I tested the let snippet using only the settings from the init.el file and data sample from issue 152. Using that criteria, all PROJ entries are suppressed from the calendar. I suggest trying the same data sample and settings that I used, and no other settings.

To test the let snippet, copy it to an empty *scratch* buffer and type M-x eval-buffer, or place the cursor at the very end of the snippet and type C-x C-e

To turn a let-bound snippet into a useful function, one would use something like this:

(defun my-func ()
  "Doc-string"
  (interactive)
  (let ((...))
    ...))
kafu16 commented 1 year ago

To test the let snippet, copy it to an empty *scratch* buffer and type M-x eval-buffer, or place the cursor at the very end of the snippet and type C-x C-e

Cool, this works. But actually I don't understand that this does not work when I put the snippet in the init.el? I thought on startup the whole init.el is evaluated? How would I make the snippet work on startup?

lawlist commented 1 year ago

You are correct that a let-bound snippet will indeed be evaluated inside the init.el when Emacs starts up. The file is read by Emacs from top to bottom, so the order in which the code is read is sometimes important; e.g., when a library needs to load before code using that library can be called. If your goal is to open the calendar automatically and have PROJ entries suppressed (using the working example from issue 152), then you might want to try placing the let-bound snippet at the very bottom of the init.el. Another idea would be to run the code on a hook that runs later in time during the startup process, e.g., emacs-startup-hook. In issue 152, the code that I used in the init.el launched the calendar view from that hook. https://github.com/kiwanami/emacs-calfw/issues/152#issuecomment-1397900614 The let-bound snippet can be added to the hook using a lambda, or the let-bound snippet can be converted to a function and the hook can call the function. In general, it is advised to attach functions to hooks so that when inspecting the hook or removing something from the hook, those processes are cleaner.

(add-hook 'emacs-startup-hook
          (lambda ()
            (let ((org-agenda-skip-function
                     '(org-agenda-skip-entry-if 'todo '("PROJ" "WAITING")))
                  (org-agenda-entry-types '(:deadline)))
              (cfw:open-org-calendar))))

OR

(add-hook 'emacs-startup-hook 'my-func)

It may be helpful to reduce your setup to the bare minimum in order to get a minimal working example that meets your criteria, e.g., use the issue 152 minimal working example, sample data set, and same init.el with the above-suggestion -- i.e., substituting the line with the emacs-startup-hook to launch the calendar using the let-bound snippet. Once you get it working, then work on your more complex custom setup.

kafu16 commented 1 year ago

Very cool, it works :). Sorry for the late reply and thank you very much for your guidance and the insights!