@@ -357,12 +357,14 @@ end
357357function Headline :set_todo (keyword )
358358 local todo , node = self :get_todo ()
359359 if todo then
360- return self :_set_node_text (node , keyword )
360+ self :_set_node_text (node , keyword )
361+ return self :update_parent_cookie ()
361362 end
362363
363364 local stars = self :_get_child_node (' stars' )
364365 local _ , level = stars :end_ ()
365- return self :_set_node_text (stars , (' %s %s' ):format ((' *' ):rep (level ), keyword ))
366+ self :_set_node_text (stars , (' %s %s' ):format ((' *' ):rep (level ), keyword ))
367+ return self :update_parent_cookie ()
366368end
367369
368370memoize (' get_todo' )
@@ -890,36 +892,74 @@ function Headline:get_cookie()
890892 return self :_parse_title_part (' %[%d?%d?%d?%%%]' )
891893end
892894
895+ function Headline :_set_cookie (cookie , num , denum )
896+ -- Update the cookie
897+ local new_cookie_val
898+ if self .file :get_node_text (cookie ):find (' %%' ) then
899+ new_cookie_val = (' [%d%%]' ):format ((num / denum ) * 100 )
900+ else
901+ new_cookie_val = (' [%d/%d]' ):format (num , denum )
902+ end
903+ return self :_set_node_text (cookie , new_cookie_val )
904+ end
905+
893906function Headline :update_cookie ()
907+ -- Update cookie state from a check box state change
908+
909+ -- Return early if the headline doesn't have a cookie
910+ local cookie = self :get_cookie ()
911+ if not cookie then
912+ return self
913+ end
914+
894915 local section = self :node ():parent ()
895916 if not section then
896917 return self
897918 end
898919
899- -- Go through all the lists in this headline and gather checked_boxes
900- local num_boxes , num_checked_boxes = 0 , 0
920+ -- Count checked boxes from all lists
921+ local num_checked_boxes , num_boxes = 0 , 0
901922 local body = section :field (' body' )[1 ]
902- for node in body :iter_children () do
903- if node :type () == ' list' then
904- local boxes = self :child_checkboxes (node )
905- num_boxes = num_boxes + # boxes
906- local checked_boxes = vim .tbl_filter (function (box )
907- return box :match (' %[%w%]' )
908- end , boxes )
909- num_checked_boxes = num_checked_boxes + # checked_boxes
923+ if body then
924+ for node in body :iter_children () do
925+ if node :type () == ' list' then
926+ local boxes = self :child_checkboxes (node )
927+ num_boxes = num_boxes + # boxes
928+ local checked_boxes = vim .tbl_filter (function (box )
929+ return box :match (' %[%w%]' )
930+ end , boxes )
931+ num_checked_boxes = num_checked_boxes + # checked_boxes
932+ end
910933 end
911934 end
912935
913- -- Update the cookie
936+ -- Set the cookie
937+ return self :_set_cookie (cookie , num_checked_boxes , num_boxes )
938+ end
939+
940+ function Headline :update_todo_cookie ()
941+ -- Update cookie state from a TODO state change
942+
943+ -- Return early if the headline doesn't have a cookie
914944 local cookie = self :get_cookie ()
915- if cookie then
916- local new_cookie_val
917- if self .file :get_node_text (cookie ):find (' %%' ) then
918- new_cookie_val = (' [%d%%]' ):format ((num_checked_boxes / num_boxes ) * 100 )
919- else
920- new_cookie_val = (' [%d/%d]' ):format (num_checked_boxes , num_boxes )
921- end
922- return self :_set_node_text (cookie , new_cookie_val )
945+ if not cookie then
946+ return self
947+ end
948+
949+ -- Count done children headlines
950+ local children = self :get_child_headlines ()
951+ local dones = vim .tbl_filter (function (h )
952+ return h :is_done ()
953+ end , children )
954+
955+ -- Set the cookie
956+ return self :_set_cookie (cookie , # dones , # children )
957+ end
958+
959+ function Headline :update_parent_cookie ()
960+ local parent = self :get_parent_headline ()
961+ if parent and parent .headline then
962+ parent :update_todo_cookie ()
923963 end
924964 return self
925965end
0 commit comments