2013-11-14 16:19:42 -05:00
;;; org-effectiveness.el --- Measuring the personal effectiveness
2017-01-05 20:19:23 -05:00
;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
2013-11-14 16:19:42 -05:00
;; Author: David Arroyo Menéndez <davidam@es.gnu.org>
;; Keywords: effectiveness, plot
;; Homepage: http://orgmode.org
;;
;; This file is not part of GNU Emacs, yet.
;;
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;; This file implements functions to measure the effectiveness in org.
;; Org-mode doesn't load this module by default - if this is not what
;; you want, configure the variable `org-modules'. Thanks to #emacs-es
;; irc channel for your support.
;;; Code:
( require 'org )
2014-03-15 04:11:54 -04:00
( defcustom org-effectiveness-max-todo 50
2016-09-23 06:19:30 -04:00
" This variable is useful to advice to the user about
2014-03-15 04:11:54 -04:00
many TODO pending "
:type 'integer
:group 'org-effectiveness )
( defun org-effectiveness-advice ( )
" Advicing about a possible excess of TODOS "
( interactive )
2016-01-25 09:24:25 -05:00
( save-excursion
( goto-char ( point-min ) )
( if ( < org-effectiveness-max-todo ( count-matches " * TODO " ) )
( message " An excess of TODOS! " ) ) ) )
2014-03-15 04:11:54 -04:00
;; Check advice starting an org file
( add-hook 'org-mode-hook 'org-effectiveness-advice )
2013-11-14 16:19:42 -05:00
( defun org-effectiveness-count-keyword ( keyword )
" Print a message with the number of keyword outline in the current buffer "
( interactive " sKeyword: " )
( save-excursion
( goto-char ( point-min ) )
( message " Number of %s: %d " keyword ( count-matches ( concat " * " keyword ) ) ) ) )
( defun org-effectiveness-count-todo ( )
" Print a message with the number of todo tasks in the current buffer "
( interactive )
2016-09-23 06:19:30 -04:00
( save-excursion
2013-11-14 16:19:42 -05:00
( goto-char ( point-min ) )
( message " Number of TODO: %d " ( count-matches " * TODO " ) ) ) )
2016-09-23 06:19:30 -04:00
2013-11-14 16:19:42 -05:00
( defun org-effectiveness-count-done ( )
" Print a message with the number of done tasks in the current buffer "
( interactive )
( save-excursion
( goto-char ( point-min ) )
( message " Number of DONE: %d " ( count-matches " * DONE " ) ) ) )
( defun org-effectiveness-count-canceled ( )
" Print a message with the number of canceled tasks in the current buffer "
( interactive )
( save-excursion
( goto-char ( point-min ) )
2013-11-16 14:12:05 -05:00
( message " Number of Canceled: %d " ( count-matches " * CANCEL+ED " ) ) ) )
2013-11-14 16:19:42 -05:00
2016-01-18 03:45:21 -05:00
( defun org-effectiveness-count-task ( )
" Print a message with the number of tasks and subtasks in the current buffer "
( interactive )
( save-excursion
( goto-char ( point-min ) )
( message " Number of tasks: %d " ( count-matches " ^* " ) ) ) )
2013-11-14 16:19:42 -05:00
( defun org-effectiveness ( )
" Returns the effectiveness in the current org buffer "
( interactive )
( save-excursion
( goto-char ( point-min ) )
( let ( ( done ( float ( count-matches " * DONE.* \n .* " ) ) )
2013-11-16 14:12:05 -05:00
( canc ( float ( count-matches " * CANCEL+ED.* \n .* " ) ) ) )
2013-11-14 16:19:42 -05:00
( if ( and ( = done canc ) ( zerop done ) )
( setq effectiveness 0 )
( setq effectiveness ( * 100 ( / done ( + done canc ) ) ) ) )
( message " Effectiveness: %f " effectiveness ) ) ) )
2016-01-25 06:07:16 -05:00
2013-11-16 14:16:03 -05:00
( defun org-effectiveness-keywords-in-date ( keyword date )
2013-11-14 16:19:42 -05:00
( interactive " sKeyword: \n sDate: " keyword date )
( setq count ( count-matches ( concat keyword " .* \n .* " date ) ) )
( message ( concat " %sS: %d " keyword count ) ) )
2016-01-25 09:24:25 -05:00
( defun org-effectiveness-dones-in-date ( date &optional notmessage )
2016-01-25 06:07:16 -05:00
( interactive " sGive me a date: " date )
( save-excursion
( goto-char ( point-min ) )
2016-01-25 09:24:25 -05:00
( let ( ( count ( count-matches ( concat " DONE.* \n .* " date ) ) ) )
( if ( eq notmessage 1 )
( message " %d " count )
( message " DONES: %d " count ) ) ) ) )
2013-11-14 16:19:42 -05:00
2016-01-25 06:07:16 -05:00
( defun org-effectiveness-todos-in-date ( date )
( interactive " sGive me a date: " date )
( save-excursion
( goto-char ( point-min ) )
( setq count ( count-matches ( concat " TODO.* \n .* " date ) ) )
( message " TODOS: %d " count ) ) )
2013-11-14 16:19:42 -05:00
2013-11-16 14:16:03 -05:00
( defun org-effectiveness-canceled-in-date ( date )
2016-01-25 06:07:16 -05:00
( interactive " sGive me a date: " date )
( save-excursion
( goto-char ( point-min ) )
( setq count ( count-matches ( concat " CANCEL+ED.* \n .* " date ) ) )
( message " CANCELEDS: %d " count ) ) )
2013-11-14 16:19:42 -05:00
2016-01-18 04:21:02 -05:00
( defun org-effectiveness-ntasks-in-date ( date &optional notmessage )
( interactive " sGive me a date: " date )
( save-excursion
( goto-char ( point-min ) )
( let ( ( tasks ( float ( count-matches ( concat " ^*.* \n .* " date ) ) ) ) )
( message " %d " tasks ) ) ) )
2013-11-14 16:19:42 -05:00
( defun org-effectiveness-in-date ( date &optional notmessage )
( interactive " sGive me a date: " date )
( save-excursion
( goto-char ( point-min ) )
( let ( ( done ( float ( count-matches ( concat " * DONE.* \n .* " date ) ) ) )
2013-11-16 14:12:05 -05:00
( canc ( float ( count-matches ( concat " * CANCEL+ED.* \n .* " date ) ) ) ) )
2013-11-14 16:19:42 -05:00
( if ( and ( = done canc ) ( zerop done ) )
( setq effectiveness 0 )
( setq effectiveness ( * 100 ( / done ( + done canc ) ) ) ) )
( if ( eq notmessage 1 )
( message " %d " effectiveness )
( message " Effectiveness: %d " effectiveness ) ) ) ) )
( defun org-effectiveness-month-to-string ( m )
( if ( < m 10 )
( concat " 0 " ( number-to-string m ) )
( number-to-string m ) ) )
2014-10-15 08:58:13 -04:00
( defun org-effectiveness-plot ( startdate enddate &optional save )
2013-11-14 16:19:42 -05:00
( interactive " sGive me the start date: \n sGive me the end date: " startdate enddate )
( setq dates ( org-effectiveness-check-dates startdate enddate ) )
2016-09-23 06:19:30 -04:00
( setq syear ( cadr ( assq 'startyear dates ) ) )
( setq smonth ( cadr ( assq 'startmonth dates ) ) )
( setq eyear ( cadr ( assq 'endyear dates ) ) )
( setq emonth ( assq 'endmonth dates ) )
2013-11-14 16:19:42 -05:00
;; Checking the format of the dates
2016-09-23 06:19:30 -04:00
( if ( not ( string-match " [0-9][0-9][0-9][0-9]-[0-9][0-9] " startdate ) )
2013-11-14 16:19:42 -05:00
( message " The start date must have the next format YYYY-MM " ) )
2016-09-23 06:19:30 -04:00
( if ( not ( string-match " [0-9][0-9][0-9][0-9]-[0-9][0-9] " enddate ) )
2013-11-14 16:19:42 -05:00
( message " The end date must have the next format YYYY-MM " ) )
;; Checking if startdate < enddate
( if ( string-match " ^[0-9][0-9][0-9][0-9] " startdate )
( setq startyear ( string-to-number ( match-string 0 startdate ) ) ) )
( if ( string-match " [0-9][0-9]$ " startdate )
( setq startmonth ( string-to-number ( match-string 0 startdate ) ) ) )
( if ( string-match " ^[0-9][0-9][0-9][0-9] " enddate )
( setq endyear ( string-to-number ( match-string 0 enddate ) ) ) )
( if ( string-match " [0-9][0-9]$ " enddate )
( setq endmonth ( string-to-number ( match-string 0 enddate ) ) ) )
( if ( > startyear endyear )
( message " The start date must be before that end date " ) )
( if ( and ( = startyear endyear ) ( > startmonth endmonth ) )
( message " The start date must be before that end date " ) )
2016-09-23 06:19:30 -04:00
;; Create a file
2013-11-14 16:19:42 -05:00
( let ( ( month startmonth )
( year startyear )
( str " " ) )
2016-09-23 06:19:30 -04:00
( while ( or ( > endyear year ) ( and ( = endyear year ) ( >= endmonth month ) ) )
2013-11-14 16:19:42 -05:00
( setq str ( concat str ( number-to-string year ) " - " ( org-effectiveness-month-to-string month ) " " ( org-effectiveness-in-date ( concat ( number-to-string year ) " - " ( org-effectiveness-month-to-string month ) ) 1 ) " \n " ) )
( if ( = month 12 )
2016-09-23 06:19:30 -04:00
( progn
2013-11-14 16:19:42 -05:00
( setq year ( + 1 year ) )
( setq month 1 ) )
( setq month ( + 1 month ) ) ) )
( write-region str nil " /tmp/org-effectiveness " ) )
2016-09-23 06:19:30 -04:00
;; Create the bar graph
2014-10-15 08:58:13 -04:00
( if ( eq save t )
( setq strplot " /usr/bin/gnuplot -e 'set term png; set output \" /tmp/org-effectiveness.png \" ; plot \" /tmp/org-effectiveness \" using 2:xticlabels(1) with histograms' -p " )
( setq strplot " /usr/bin/gnuplot -e 'plot \" /tmp/org-effectiveness \" using 2:xticlabels(1) with histograms' -p " ) )
2013-11-14 16:19:42 -05:00
( if ( file-exists-p " /usr/bin/gnuplot " )
2014-10-15 08:58:13 -04:00
( call-process " /bin/bash " nil t nil " -c " strplot )
2013-11-14 16:19:42 -05:00
( message " gnuplot is not installed " ) ) )
2014-10-15 08:58:13 -04:00
( defun org-effectiveness-plot-save ( startdate enddate &optional save )
( interactive " sGive me the start date: \n sGive me the end date: " startdate enddate )
( org-effectiveness-plot startdate enddate t ) )
;; (defun org-effectiveness-plot(startdate enddate)
2013-11-14 16:19:42 -05:00
( defun org-effectiveness-ascii-bar ( n &optional label )
" Print a bar with the percentage from 0 to 100 printed in ascii "
( interactive " nPercentage: \n sLabel: " )
( if ( or ( < n 0 ) ( > n 100 ) )
( message " The percentage must be between 0 to 100 " )
( let ( ( x 0 )
( y 0 )
( z 0 ) )
( insert ( format " \n ### %s ### " label ) )
( insert " \n - " )
( while ( < x n )
( insert " - " )
( setq x ( + x 1 ) ) )
( insert " + \n " )
( insert ( format " %d " n ) )
( if ( > n 10 )
( setq y ( + y 1 ) ) )
( while ( < y n )
( insert " " )
( setq y ( + y 1 ) ) )
( insert " | \n " )
( insert " - " )
( while ( < z n )
( insert " - " )
( setq z ( + z 1 ) ) )
( insert " + " ) ) ) )
2014-05-04 10:29:34 -04:00
( defun org-effectiveness-html-bar ( n &optional label )
" Print a bar with the percentage from 0 to 100 printed in html "
( interactive " nPercentage: \n sLabel: " )
( if ( or ( < n 0 ) ( > n 100 ) )
( message " The percentage must be between 0 to 100 " )
( let ( ( x 0 )
( y 0 )
( z 0 ) )
( insert ( format " \n <div class='percentage-%d'>%d</div> " n n ) )
) ) )
2013-11-14 16:19:42 -05:00
( defun org-effectiveness-check-dates ( startdate enddate )
" Generate a list with ((startyear startmonth) (endyear endmonth)) "
( setq str nil )
2016-09-23 06:19:30 -04:00
( if ( not ( string-match " [0-9][0-9][0-9][0-9]-[0-9][0-9] " startdate ) )
2013-11-14 16:19:42 -05:00
( setq str " The start date must have the next format YYYY-MM " ) )
2016-09-23 06:19:30 -04:00
( if ( not ( string-match " [0-9][0-9][0-9][0-9]-[0-9][0-9] " enddate ) )
2013-11-14 16:19:42 -05:00
( setq str " The end date must have the next format YYYY-MM " ) )
;; Checking if startdate < enddate
( if ( string-match " ^[0-9][0-9][0-9][0-9] " startdate )
( setq startyear ( string-to-number ( match-string 0 startdate ) ) ) )
( if ( string-match " [0-9][0-9]$ " startdate )
( setq startmonth ( string-to-number ( match-string 0 startdate ) ) ) )
( if ( string-match " ^[0-9][0-9][0-9][0-9] " enddate )
( setq endyear ( string-to-number ( match-string 0 enddate ) ) ) )
( if ( string-match " [0-9][0-9]$ " enddate )
( setq endmonth ( string-to-number ( match-string 0 enddate ) ) ) )
( if ( > startyear endyear )
( setq str " The start date must be before that end date " ) )
( if ( and ( = startyear endyear ) ( > startmonth endmonth ) )
( setq str " The start date must be before that end date " ) )
( if str
( message str )
;; (list (list startyear startmonth) (list endyear endmonth))))
( list ( list 'startyear startyear ) ( list 'startmonth startmonth ) ( list 'endyear endyear ) ( list 'endmonth endmonth ) ) ) )
( defun org-effectiveness-plot-ascii ( startdate enddate )
( interactive " sGive me the start date: \n sGive me the end date: " startdate enddate )
( setq dates ( org-effectiveness-check-dates startdate enddate ) )
2016-09-23 06:19:30 -04:00
( let ( ( syear ( cadr ( assq 'startyear dates ) ) )
( smonth ( cadr ( assq 'startmonth dates ) ) )
( year ( cadr ( assq 'startyear dates ) ) )
( month ( cadr ( assq 'startmonth dates ) ) )
( emonth ( cadr ( assq 'endmonth dates ) ) )
( eyear ( cadr ( assq 'endyear dates ) ) )
2014-03-15 06:02:51 -04:00
( buffer ( current-buffer ) )
2013-11-14 16:19:42 -05:00
( str " " ) )
2014-03-15 06:02:51 -04:00
( while ( or ( > eyear year ) ( and ( = eyear year ) ( >= emonth month ) ) )
( setq str ( org-effectiveness-in-date ( concat ( number-to-string year ) " - " ( org-effectiveness-month-to-string month ) ) 1 ) )
( switch-to-buffer " *org-effectiveness* " )
( org-effectiveness-ascii-bar ( string-to-number str ) ( format " %s-%s " year month ) )
( switch-to-buffer buffer )
2014-03-15 05:15:34 -04:00
( if ( eq month 12 )
2016-09-23 06:19:30 -04:00
( progn
2013-11-14 16:19:42 -05:00
( setq year ( + 1 year ) )
( setq month 1 ) )
2014-03-15 06:02:51 -04:00
( setq month ( + 1 month ) ) ) ) )
( switch-to-buffer " *org-effectiveness* " ) )
2016-01-18 04:21:02 -05:00
( defun org-effectiveness-plot-ascii-ntasks ( startdate enddate )
( interactive " sGive me the start date: \n sGive me the end date: " startdate enddate )
( setq dates ( org-effectiveness-check-dates startdate enddate ) )
2016-09-23 06:19:30 -04:00
( let ( ( syear ( cadr ( assq 'startyear dates ) ) )
( smonth ( cadr ( assq 'startmonth dates ) ) )
( year ( cadr ( assq 'startyear dates ) ) )
( month ( cadr ( assq 'startmonth dates ) ) )
( emonth ( cadr ( assq 'endmonth dates ) ) )
( eyear ( cadr ( assq 'endyear dates ) ) )
2016-01-18 04:21:02 -05:00
( buffer ( current-buffer ) )
( str " " ) )
( while ( or ( > eyear year ) ( and ( = eyear year ) ( >= emonth month ) ) )
( setq str ( org-effectiveness-ntasks-in-date ( concat ( number-to-string year ) " - " ( org-effectiveness-month-to-string month ) ) 1 ) )
( switch-to-buffer " *org-effectiveness* " )
( org-effectiveness-ascii-bar ( string-to-number str ) ( format " %s-%s " year month ) )
( switch-to-buffer buffer )
( if ( eq month 12 )
2016-09-23 06:19:30 -04:00
( progn
2016-01-18 04:21:02 -05:00
( setq year ( + 1 year ) )
( setq month 1 ) )
( setq month ( + 1 month ) ) ) ) )
( switch-to-buffer " *org-effectiveness* " ) )
2016-01-25 09:24:25 -05:00
( defun org-effectiveness-plot-ascii-dones ( startdate enddate )
( interactive " sGive me the start date: \n sGive me the end date: " startdate enddate )
( setq dates ( org-effectiveness-check-dates startdate enddate ) )
2016-09-23 06:19:30 -04:00
( let ( ( syear ( cadr ( assq 'startyear dates ) ) )
( smonth ( cadr ( assq 'startmonth dates ) ) )
( year ( cadr ( assq 'startyear dates ) ) )
( month ( cadr ( assq 'startmonth dates ) ) )
( emonth ( cadr ( assq 'endmonth dates ) ) )
( eyear ( cadr ( assq 'endyear dates ) ) )
2016-01-25 09:24:25 -05:00
( buffer ( current-buffer ) )
( str " " ) )
( while ( or ( > eyear year ) ( and ( = eyear year ) ( >= emonth month ) ) )
( setq str ( org-effectiveness-dones-in-date ( concat ( number-to-string year ) " - " ( org-effectiveness-month-to-string month ) ) 1 ) )
( switch-to-buffer " *org-effectiveness* " )
( org-effectiveness-ascii-bar ( string-to-number str ) ( format " %s-%s " year month ) )
( switch-to-buffer buffer )
( if ( eq month 12 )
2016-09-23 06:19:30 -04:00
( progn
2016-01-25 09:24:25 -05:00
( setq year ( + 1 year ) )
( setq month 1 ) )
( setq month ( + 1 month ) ) ) ) )
( switch-to-buffer " *org-effectiveness* " ) )
2014-05-04 10:29:34 -04:00
( defun org-effectiveness-plot-html ( startdate enddate )
" Print html bars about the effectiveness in a buffer "
( interactive " sGive me the start date: \n sGive me the end date: " startdate enddate )
( setq dates ( org-effectiveness-check-dates startdate enddate ) )
2016-09-23 06:19:30 -04:00
( let ( ( syear ( cadr ( assq 'startyear dates ) ) )
( smonth ( cadr ( assq 'startmonth dates ) ) )
( year ( cadr ( assq 'startyear dates ) ) )
( month ( cadr ( assq 'startmonth dates ) ) )
( emonth ( cadr ( assq 'endmonth dates ) ) )
( eyear ( cadr ( assq 'endyear dates ) ) )
2014-05-04 10:29:34 -04:00
( buffer ( current-buffer ) )
( str " " ) )
( switch-to-buffer " *org-effectiveness-html* " )
( insert " <html><head><title>Graphbar</title><meta http-equiv='Content-type' content='text/html; charset=utf-8'><link rel='stylesheet' type='text/css' href='graphbar.css' title='graphbar'></head><body> " )
( while ( or ( > eyear year ) ( and ( = eyear year ) ( >= emonth month ) ) )
( setq str ( org-effectiveness-in-date ( concat ( number-to-string year ) " - " ( org-effectiveness-month-to-string month ) ) 1 ) )
( switch-to-buffer " *org-effectiveness-html* " )
( org-effectiveness-html-bar ( string-to-number str ) ( format " %s-%s " year month ) )
( switch-to-buffer buffer )
( format " %s-%s " year month )
( if ( eq month 12 )
2016-09-23 06:19:30 -04:00
( progn
2014-05-04 10:29:34 -04:00
( setq year ( + 1 year ) )
( setq month 1 ) )
( setq month ( + 1 month ) ) ) )
( switch-to-buffer " *org-effectiveness-html* " )
( insert " </body></html> " ) ) )
2013-11-14 16:19:42 -05:00
( provide 'org-effectiveness )