4

I am trying to track my diet using org-mode. The workflow so far looks like this:

  • Nutritional value data is stored in a file (Food_DB.org) where each food is represented by an org item with nutritional values as properties

  • The food I eat during a day is captured in the datetree of another file (Food.org). I use a capture template that allows to copy items from the Food_DB.org to the current day in the datetree of Food.org. After copying I set an additional property "WEIGHT" in this copy of the food item located in Food.org

  • This step is problematic: I would like to be able to see a summary of nutritional values for the day using column view. This is my approach to this:

    (eval-when-compile (require 'dash-functional))
    
    (defun org--nutri-product (val weight)
      (* (float val) (/ (float weight) 100.0)))
    
    (defun org--nutri-get-weight ()
      (with-current-buffer "Food.org"
        (string-to-number (org-entry-get nil "WEIGHT"))))
    
    (defun org--columns-summary-nutritional (values printf)
      (format (or printf "%s")
              (apply #'+ (mapcar (-cut org--nutri-product <> (org--nutri-get-weight))
                                 (mapcar #'string-to-number values)))))
    

    where org--columns-summary-nutritional is used as a org-column summary function.

Where this actually breaks is the function org--nutri-get-weight. What I intend to do there: Obtain the WEIGHT property from the item the org column view functionality is currently looking at, which is required to calculate the actual amounts of nutrients that have been consumed. I attempt to do this using org-entry-get since this is the only function from the org-property API that makes sense to me to do something like this. However, when I activate column view, it looks like this function gets called on some item but not one that actually has the WEIGHT property, which causes an error since nil is returned. I do not know whether I am using the function the wrong way since it can take a marker as an argument and I am not proficient in markers. On the other hand, the functionality I require here looks to me like something the developers of Org-mode have very likely thought of and already implemented. (At least that is what I would do if I was skilled enough to hack the org-core)

The question in short: Am I using the functions the wrong way, is there another de facto org function to use for this or will I have to engage in a big regex-orgy?

Minimum working example for org--nutri-get-weight

If org--nutri-get-weight is evaluated while cursor is on one of those headings, it returns the WEIGHT value.

**** Erdnussbutter
 :PROPERTIES:
 :KCAL:     629
 :PROTEIN:  25.4
 :FETT:     50.8
 :KOHLENHYDRATE: 15.2
 :WEIGHT: 38
 :END:
**** Vollmilch
 :PROPERTIES:
 :KCAL:     65
 :FETT:     3.6
 :KOHLENHYDRATE: 4.8
 :PROTEIN:  3.3
 :WEIGHT: 309
 :END:
  • It sounds like the first thing to do is evaluate (point) when you call your custom function and see where you are, and then you can determine where (if anywhere else) you need to go to get the value you desire. And, also try going to that same point without column-view and see if your custom function behaves the same. – lawlist Oct 17 '17 at 17:13
  • How would that "going somewhere" work programmatically? – Aaron Meinel Oct 17 '17 at 17:35
  • When I run the function while the cursor is on an org headline that has the desired property it returns the value. – Aaron Meinel Oct 17 '17 at 17:40
  • That depends on where you want to go. Because there is no minimal working example for us to reproduce what it is that you are observing, the question is not presently answerable. You might be one point before the desired heading, you might be one point after the heading, you might be somewhere else. – lawlist Oct 17 '17 at 17:41
  • Additional tools you may wish to use include, but are not limited to examining markers and text-properties at point: (text-properties-at (point)), org-entry-properties, ... – lawlist Oct 17 '17 at 17:46
6

Answer to the short version of this question: The de facto org function to obtain information on org items is org-map-entries which for this case could be used as follows

(org-map-entries (lambda () (org-entry-get nil   "WEIGHT"))
    "+WEIGHT>0")))

where the lambda expression retrieves the value of property "WEIGHT" from each item that is visited by org-map-entries. org-map-entries only visits those items whose property "WEIGHT" has a value larger than 0. This makes sense from a physical point of view, but it is used this way because there is no obvious way of just mapping on any items that have the property at all, so this is a convenient solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.