pax_global_header00006660000000000000000000000064122646231470014521gustar00rootroot0000000000000052 comment=145e9e35f2c2fd362e15867f227f9c102e941894 planner-el/000077500000000000000000000000001226462314700131225ustar00rootroot00000000000000planner-el/.gitignore000066400000000000000000000002131226462314700151060ustar00rootroot00000000000000# Files that we ignore when using git. *~ /++xgit-log-edit *.elc # /Makefile.defs /planner-autoloads.el /planner-el.info /planner-el.html planner-el/AUTHORS000066400000000000000000000223071226462314700141760ustar00rootroot00000000000000Planner ======= This is a listing of those who have made contributions of code or documentation to Planner. John Wiegley: Original author (assigned past and future changes for Emacs) John Sullivan: Current maintainer Author of: - planner-el.texi (assigned past and future changes) Michael Olson: Previous maintainer (2005-11-01 to 2006-06-27) (assigned past and future changes for Emacs) Sacha Chua: Previous maintainer (2004-01-01 to 2005-10-31) Author of: - planner-accomplishments.el - planner-cyclic.el - planner-deadline.el - planner-erc.el - planner-experimental.el - planner-id.el - planner-lisp.el - planner-multi.el - planner-notes-index.el - planner-rmail.el - planner-rss.el - planner-tasks-overview.el - planner-vm.el Contributor: (changes too numerous to list) (assigned past and future changes) Adrian Aichner: Contributor: - planner.el - planner-gnus.el - planner-timeclock.el (assigned past and future changes for Emacs) Keith Amidon: Contributor: - planner-trunk.el (15+ lines changed) Dirk Bernhardt: Contributor: - planner.el (15+ lines changed) Trent Buck: Contributor: - planner-timeclock-summary-proj.el (15+ lines changed) - planner.el (11 lines changed) Fran Burstall: Contributor: - planner-vm.el (1 line changed) James Clarke: Author of planner-bibtex.el Jeremy Cowgar: Author of: - planner-gnats.el Contributor: - planner-wl.el (6 lines changed) Mario Domgörgen: Contributor: - planner-gnus.el (15+ lines changed) Jürgen Doser: Contributor: - planner-vm.el (15+ lines changed) (assigned past and future changes) drkm : Contributor: - planner-calendar.el (4 lines changed) Seth Falcon: Contributor: - planner-appt.el - planner-multi.el (1 line changed) - planner-psvn.el (12 lines changed) - planner-report.el (7 lines changed) Gerd Flaig: Contributor: - planner-lisp.el (1 line changed) Frederik Fouvry: Author of: - planner-unix-mail.el Contributor: - planner-rmail.el (15+ lines changed) - planner.el (14 lines changed) (disclaimed changes for Emacs) Romain Francoise: Contributor: - planner.el (4 lines changed) (assigned changed for Emacs) Christophe Garion: Author of planner-mhe.el Thomas Gehrlein: Author of planner-diary.el Marco Gidde: Contributor: - planner-multi.el (6 lines changed) - planner.el (9 lines changed) Will Glozer: Author of planner-ledger.el Bastien Guerry: Author of planner-registry.el Henrik S. Hansen: Contributor: - planner-appt.el Travis B. Hartwell: Contributor - planner-diary.el - planner-ledger.el (assigned past and future changes) Magnus Henoch: Contributor: - planner-gnus.el (5 lines changed) Yann Hodique: Contributor: - planner-bbdb.el (6 lines changed) - planner-export-diary.el (1 line changed) - planner-gnus.el (4 lines changed) - planner-id.el (1 line changed) - planner-log-edit.el (15+ lines changed) - planner-mhe.el (3 lines changed) - planner-multi.el (7 lines changed) - planner-notes-index.el (1 line changed) - planner-psvn.el (4 lines changed) - planner-report.el (1 line changed) - planner-tasks-overview.el (2 lines changed) - planner-timeclock.el (4 lines changed) - planner-unix-mail.el (4 lines changed) - planner-xtla.el (15+ lines changed) - planner.el (15+ lines changed) (assigned past and future changes for Muse) Markus Hoenicka: Contributor: - planner-publish.el (4 lines changed) Xin Wei Hu: Contributor: - planner-export-diary.el JM Ibanez: Contributor: - planner-calendar.el (small patch) Maciej Kalisak: Contributor: - planner.el (15+ lines changed) Sven Kloppenburg: Contributor: - planner-gnus.el (5 lines changed) - planner.el (1 line changed) Jody Klymak: Contributor: - planner-bibtex.el - planner-diary.el (documentation) Andrew J. Korty: Author of: - planner-authz.el - planner-report.el Contributor: - planner-bbdb.el - planner-publish.el (1 line changed) - planner-tasks-overview.el (1 line changed) - planner.el (1 line changed) Peter K. Lee: Author of: - planner-publish.el Contributor: - planner-accomplishments.el (2 lines changed) - planner-timeclock-summary.el (15+ lines changed) - planner-timeclock.el (15+ lines changed) - planner.el (15+ lines changed) Angus Lees: Contributor: - planner-wl.el (15+ lines changed) - planner.el (15+ lines changed) Wei-Hao Lin: Contributor: - planner-bibtex.el (1 line changed) Dryice Dong Liu: Author of: - planner-bookmark.el - planner-rank.el - planner-timeclock-summary.el - planner-trunk.el Contributor: - planner-deadline.el - planner-log-edit.el (12 lines changed) - planner-el.texi (15+ lines changed) - planner.el (15+ lines changed) Deus Max: Contributor: - planner-ledger.el (15+ lines changed) (assigned past and future changes) Chris McMahan: Contributor: - planner-publish.el (15+ lines changed) Daniel Neri: Contributor: - planner-gnus.el (~10 lines changed) - planner.el (~5 lines changed) Greg Novak: Author of: - planner-zoom.el Contributor: - planner-vm.el (1 line changed) Jim Ottaway: Author of: - planner-appt.el Contributor: - planner-bibtex.el - planner-el.texi - planner-id.el - planner-lisp.el - planner-multi.el - planner-publish.el - planner.el (assignment pending) Chris Parsons: Author of: - planner-ical.el Contributor: - planner-timeclock-summary.el (15+ lines changed) - planner.el (15+ lines changed) Mario Peter: Contributor: - planner.el (1 line changed) Pascal Quesseveur: Author of planner-timeclock-summary-proj.el Stefan Reichör: Author of: - planner-psvn.el - planner-xtla.el Contributor: - planner-gnus.el (6 lines changed) - planner.el (15+ lines changed) (assigned past and future changes) Marko Schütz: Contributor: - planner-timeclock-summary-proj.el (1 line changed) Dale P. Smith: Contributor: - planner-gnus.el (2 lines changed) - planner-publish.el (15+ lines changed) - planner.el (2 lines changed) (disclaimed changes for Emacs and Muse) David D. Smith: Contributor: - planner-publish.el - planner-rss.el (15+ lines changed) - planner.el (15+ lines changed) Yvonne Thomson: Author of: - planner-wl.el Contributor: - planner.el (15+ lines changed) Hoan Ton-That: Contributor: - planner.el (~10 lines changed) Win Treese: Contributor: - planner.el (4 lines changed) Mark Triggs: Contributor (assigned past and future changes for Emacs) Gary V. Vaughan: Author of planner-calendar.el (assigned past and future changes for Emacs) Thierry Vilpiatto: Contributor: - planner-ledger.el (5 lines changed) Sergey Vlasov: Contributor: - planner-appt.el (1 line changed) - planner-cyclic.el - planner-multi.el (14 lines changed) - planner-trunk.el (12 lines changed) - planner.el (15+ lines changed) Rainer Volz: Author: - planner-rdf.el - planner-rdf.owl Simon Winwood: Author of planner-log-edit.el Contributed software ==================== This is a listing of authors of software in the `contrib' directory. Adrian Aichner: Contributor: - timeclock.el (15+ lines changed) John Wiegley: Author: - schedule.el - timeclock.el ;; Local Variables: ;; coding: utf-8 ;; End: planner-el/COMMENTARY000066400000000000000000000306271226462314700145330ustar00rootroot00000000000000---------------------------------------------------------------- Note: This is one way of planning. It isn't the only way of planning, and we will gladly help you find yours. =) - Sacha Chua ---------------------------------------------------------------- Commentary by John Wiegley (johnw AT gnu DOT org) What is planning? It can be a nebulous thing to define. In its essence, however, it is very simple: it's how we achieve our dreams. Our days are filled with time, and hence with actions, whether they be of a mental or physical sort. But there are two kinds of action: reactive and creative. Reactive action is a response to the environment, a reaction to stimulus. Had we enough instincts to ensure survival, we could live according to this kind of action alone. It is a mode of behavior we share with every living species. The opposite to reactivity is creativity, when we decide upon a course of action that is a wholly a product of personal choice. We then make decisions as to the steps needed to make this wish a reality. This is planning. Planning is essentially a creative endeavor at every step. First, create the idea, what you want to achieve. Very short-term ideas do not need much more than thinking about how to do it. But long-term ideas require planning, since the mind cannot contain all of the details. Second, decide how the idea maps into the circumstances you find yourself in. Some environments will assist your plan, others hinder it. But step by step, identify every barrier to the realization of your idea, and devise a countermeasure to overcome it. Once you've mapped things out from beginning to end, accounting for unknowables as best you can, you now have your plan. Third is to break the stages of the plan into parts that are not overwhelming in their complexity. It is at during this phase that a plan is turned into task items, each to be accomplished within the span of one day's time. If a task requires several days, break it up further. The smaller it is, the less your mind will recoil from attempting it. Fourth is to monitor your progress, identifying problems and correcting for them as you go. Some plans start out unachievable, and remain that way indefinitely, due to a simple lack of observation. If nothing is working for you, change it. Otherwise, your plan is merely a well-crafted wish. Fifth is just to do the work, and be patient. All good plans take a great deal of time, and *cannot* happen immediately. The groundwork must be laid for each step, or else it will rest on an unsecure foundation. If you follow your plan doggedly, applying some time to it each day or week, it _will_ happen. Remember the story of the tortoise and the hare. I've even written a short essay on the necessity of gradual accomplishment, which can be found at http://emacswiki.org/johnw/essays/node2.html . How can this software help? Computers are ideal for manipulating information, since they allow you to change things without erasing or rewriting. And since all plans change quite a bit during their implementation, a planning program can be very helpful. Start by adding the following to your .emacs file: (load "planner") Now, conceive your idea. I can't believe there's nothing you want from life. More peace, time to enjoy the world, an end to war? Everyone wants something. Search deeply, and you will find countless unhoped wishes lurking therein. Choose one for now, and think on it for a while. Then open a file (using C-x C-f) within the directory named by `planner-directory'. Emacs will automatically recognize this file as a planner file. Name the file after your plan, such as "BetterHealth". Choose an idea you really want to accomplish. Struggle to differentiate between the things you want because others want them, and the things you want for yourself. It takes quite an effort, and may require a long time before you notice the difference. Many people want to be more healthy to be more attractive, which is an externally driven goal. Unless _you_ really want to accomplish what you envision, the odds are you will fail. Only our own wishes and dreams possess enough personal energy to see themselves to fruition. What happens to many of us is simply that we never become conscious of these dreams: what we love, what we desire most. When I talk to friends, so much of what I hear is things they want because they feel they should want them. There's just not enough energy there to pursue a good plan, because nearly all of it is negative energy. Do you know what you really want? Don't worry, many people don't. It's not a question anyone really wants us to pursue, because often we don't want what others do; it doesn't contribute to the social welfare, and all that nonsense. Somehow we always forget that what's good for the social welfare now, was someone else's crazy dream a hundred years ago. The human aversion to fundamental change is always one's greatest enemy, so don't waste any time getting bitter about it. For the sake of argument I assume you really do want to be healthier, because you've fallen in love with the ideal of purity, or you understand the connection between your physical self and the world around you, and how this can open up your spirit to desiring more. I assume. :) So you're in a Wiki file called BetterHealth. Start typing. Type anything related to your idea: what you think about it, your ideas on it, *and especially what the end will look like*. If you can't visualize the end, you can't plan, since planning is about drawing a line between now and then. When you've typed enough to gain a vision of your goal, start drafting what the possible intermediate steps might be. Then stop, get up, walk around, enjoy life, and come back to it. Taking a long time at the beginning is not a bad idea at all, as long as it's not forever. As you chew on your idea, it will begin to become more and more concrete. You'll have ideas about the smallest pieces, and ideas about the biggest pieces. Keep going until it starts to take shape before you, and you can see yourself in your mind's eye moving from the present into the future. Write down this progression, and the sorts of things you might encounter along the way. As you continue, you'll naturally discover discrete phases, or "milestones" as managers love to call them. These are very important, because they let you know you're making progress. I recommend having a big party with friends every time you achieve a milestone. A typical plan might have between three and ten. Between the milestones are the bigger pieces of your plan. Name these pieces using MixedCase words, and you'll notice that Emacs colors and underlines them for you. Like, FindGoodGym. Hit return on this highlighted word, and you'll find yourself in another, blank file. In this file, start drafting your sub-plan, just as you did with the larger plan. You should find it easier now, since the scope is smaller. As you break down further, you'll notice simple little things that need to get done. These are your tasks. Every plan is a succession of tasks. The difference from reactivity is that each task is part of the larger plan. This is what it means to be systematic: that everything you do helps further your plan. If you have tasks in your day that contribute to no plan, they are reactive. Of course, life is full of these, but don't let them take up more than 20% of your day. If you allow yourself to be dominated by reactive tasks, you'll regret it at the end of your life. I don't know this personally, but I do know that striving for one's dreams -- and seeing them come to fruition -- is the greatest joy a man can possess. It is the essence of freedom, of living, of creation. Reactivity is the opposite of this, and serves only to drain our energy and slacken our spirits. Now that you've thought of a simple task, type C-c C-t. This will ask for a brief description of the task, and when you plan to do it. If you hit RETURN at the question 'When', it assumes you mean today. The Planner will also pop up a three-month calendar at this question, so you can see where your free days are. Make sure you set the variable `mark-diary-entries-in-calendar' to t in your .emacs file. This way, you can see which days your appointments fall on. (Read about the Emacs Calendar and Diary in the Emacs info manual). (setq mark-diary-entries-in-calendar t) Once your task is in there, go back to your plan and keep generating more tasks. Generate them all! Fully describe -- as tasks -- everything necessary to bring your sub-plan to completion. Don't create tasks for the other sub-plans. You may have good idea of what they'll look like, but don't bother rendering them into tasks just yet. Things will change too much between now and then, for that to be a good use of your time. Is your sub-plan now rendered into all of the tasks necessary to reach your first milestone? Great! That is the purpose of planner.el. The rest is really up to you. If you find that you keep putting things off, and never do them, that's the surest sign you're planning for someone else's dream, and not your own. Here are some of the things planner.el can do, to help you manage and track your tasks: At the beginning of every day, type M-x plan. This will jump you to the top of the most recent task list before today. If you skipped a bunch of days, you'll have to open up those files on your own. Probably some of the tasks that day won't be finished -- that's OK. Learning to properly estimate time is a magical, mystical art that few have mastered. Put your cursor on those undone tasks, and type C-c C-c. This will move them into today's task page. You can jump to today's task page at any time by typing C-c C-n (from a Wiki or planning page). I heartily recommend binding C-c n, to jump you to this page from anywhere: (define-key mode-specific-map [?n] 'planner-goto-today) As you look at your task sheet each day, the first thing to do is to "clock in" to one of them. This isn't necessary, and is only helpful if you're around your computer a lot. But by typing C-c C-i (assuming you have my timeclock.el on your load-path), it will log the time you spend working on your sub-plan. This is helpful for viewing your progress. Type C-c C-o to clock out. C-c C-u and C-c C-d will move a task up and down in priority. The priority scheme has two components: a letter A through C, and a number from 1 onwards. 'A' tasks mean they must be done that day, or else your plan is compromised and you will have to replan. 'B' means they should be done that day, to further the plan, otherwise things will be delayed. 'C' means you can put off the task if you need to, although ultimately it will have to be done. For reactive tasks, the letters mean something different: 'A' means you must do it today, or somebody will roast your chestnuts over an open fire. 'B' means you should do it today, or else someone will be practicing patience at the day's end. 'C' means no one will notice if you don't do it. Again, reactive tasks are ENEMIES OF PLANNING. Really, until you see them that way, circumstances will push you around and steal your life away. We have only so many years to use, and everyone is greedy to take them. It's insidious, almost invisible. A healthy dislike of reactivity will do wonders for organizing your affairs according to their true priority. The last word that needs to be said concerns "roles". Every person stands in several positions in his life: husband, employee, manager, etc. These roles will tend to generate tasks not associated with any immediate plan, but necessary to maintain the health and functioning of the role. My suggestion is to keep this the smallest possible number, and fulfill those that remain well. How you decide to apportion your time between pursuing grand designs, and fostering deep relationships, is a personal matter. If you choose well, each will feed the other. I mention this to point that reactivity is something not exclusively associated with tasks that have no master plan, because being a father, for example, is something that rarely proceeds according to orderly plans. But the role of father itself is its own plan, whose goal is "to be the best one can", and whose component tasks are spending time on whatever comes up. It is, in a sense, an implicit plan. But reactive tasks follow no plan at all; they are parasites of time that suck the spirit away, whereas properly chose roles actually help fulfill one's own inner needs. At least, this is what I believe. planner-el/COPYING000066400000000000000000001045131226462314700141610ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program 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. This program 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 this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . planner-el/ChangeLog000066400000000000000000000463141226462314700147040ustar00rootroot000000000000002014-01-12 John Sullivan * planner-el.texi: Several updates to fix broken cross-references and outdated instructions. Still more to do. 2009-07-11 John Sullivan * planner-el.texi (Planning based on the Franklin-Covey Approach): Fix broken link reported by Andrew Boocock. 2009-02-18 John Sullivan * planner.el (plan): When carrying tasks forward, narrow to the tasks section first instead of looking at the whole page. Closes #11948. This should also improve performance a good deal for everyone using `planner-carry-tasks-forward'. 2009-02-17 John Sullivan * planner-multi.el (planner-multi-read-name): I don't think the value for `crm-separator' sohuld be regexp quoted. If we're using crm, then we need to modify its completion map in the same way we do if we're not. I'm setting up the map inside the function instead of defvar because I'm concerned about what happens when people modify `planner-multi-separator' after loading planner-multi. Better ways of doing this welcome, but it seems to work. 2009-02-15 John Sullivan * planner.el (planner-annotation-from-file-relative): Delete this function; nothing is using it. * planner-el.texi: Remove obsolete mentions of planner-directory. * planner-multi.el (planner-multi-read-name): Using SPC as the planner-multi-separator no longer breaks SPC completion for other Emacs functions. Closes #11953. 2009-02-14 John Sullivan * planner.el, planner-deadline.el, planner-notes-index.el, planner-rank.el, planner-rdf.el, planner-timeclock-summary.el, planner-trunk.el: Finally merge patch from Bradley Kuhn at the Software Freedom Law Center to allow "-" to be used as the date separator. A customizable variable, planner-date-separator, allows the user to choose which separator they prefer. The regexes that match dates throughout the planner codebase have been changed to match both. Closes #8205. 2009-02-08 John Sullivan * planner-el.texi (Publishing Planner pages): Fix typo, closes #12843. 2008-06-30 John Sullivan * planner.el (planner-list-daily-files): Clarify docstring. (planner-get-day-pages): planner-list-daily-files only returns date pages, no need to test for this. 2008-06-30 Michael Olson * planner.el (planner-list-daily-files): Fix Bug #11932, where duplicate items could be returned in planner-get-day-pages. 2008-06-29 John Sullivan * planner.el (planner-create-note): Fix for #10196, make sure that newly created notes get the right number. * planner-el.texi (Keeping Track of Time): Recover paragraph that had been lost sometime in 2005. 2008-05-18 John Sullivan * Release Planner 3.42. 2008-04-26 Michael Olson * planner.el (planner-copy-or-move-region): Make sure that the very first task in a region is acted on exactly once. The old behavior was that the first task would be skipped. 2008-04-16 Michael Olson * Makefile (distclean): Don't bother removing debian files. (debclean, debprepare, debbuild, debinstall, deb): Remove obsolete targets. * Makefile.defs.default (DEBNAME, LASTUPLOAD, BUILDOPTS) (DISTRIBUTOR): Remove obsolete variables. * planner.el (planner-annotation-from-wiki): Use "::" instead of "#" as the project/page delimiter. 2008-02-24 Michael Olson * planner-report.el (planner-report-generate): Use insert-file-contents instead of insert-file-contents-literally. Otherwise non-ASCII characters get mangled. Thanks to Michael Heerdegen for the report. 2008-01-20 Sacha Chua * planner-rss.el (planner-rss-add-item): Remove call to muse-publish-markup-region. (planner-publish-markup-note-rss): Use muse-insert-markup so that markup doesn't get escaped. 2007-12-27 Deus Max * planner-ledger.el (planner-ledger): New customize group. (planner-ledger-data-file): New option specifying ledger file to use. (planner-ledger-balance-regexp, planner-ledger-pending-regexp) (planner-ledger-balance-args): Update to work with newer versions of ledger. (planner-ledger-insert-balance-maybe): New function. (planner-ledger-insert-pending-maybe): New function. (planner-ledger-insert-section-maybe): Add newlines. (planner-ledger-clear-section-balance) (planner-ledger-clear-section-pending) (planner-ledger-clear-section, planner-ledger-goto-section-end): New functions. (planner-ledger-add-entry-from-task): Use planner-ledger-data-file. Use more precise entry format. (planner-ledger-run-ledger): New function to run ledger. 2007-12-04 Michael Olson * planner-el.texi: Update to mention git instructions, rather than Arch. 2007-12-02 Jim Ottaway * planner-appt.el: Move advice higher in file. (planner-appt-update-appt-section-maybe): Fix bug with planner-deadline and task-based appointments. 2007-11-28 Markus Hoenicka * planner-publish.el (planner-html-markup-strings): Add id to planner-begin-task string. (planner-publish-task-tag): Pass an appropriate id argument. If using task numbers, concatenate the priority and the task number. Otherwise, concatenate the priority with a pseudo-random number. 2007-10-29 Adrian Aichner * contrib/timeclock.el: Typo fix. * planner-gnus.el (planner-gnus-get-message-id): Make gnuslog (see http://www.emacswiki.org/cgi-bin/wiki/GnusLog) URLs useful in context of current gnuslog-file. * planner-timeclock.el (defadvice planner-replan-task): Make project match optional (for tasks added manually). 2007-10-28 Michael Olson * Makefile (DEFS): Use more-sophisticated Makefile.defs.default setup. (info-only): New rule to make just the info file. (install): Use improved install_info method. (dist, debprepare): Update rules for git. (elpa): New rule that makes an ELPA package for Planner. * Makefile.defs.default: Rename from Makefile.defs. (install_info): New improved rule based on the old INSTALLINFO variable. (ELPADIR, ELPADESC): New variables used for making the Planner ELPA package. 2007-09-26 John Sullivan * planner.el (planner-search-notes-internal): Don't include the title line of any following note in either the search or the matched text. Closes #8973 and #7622. * All files: Relicense to GPLv3, add new COPYING text and update manual. 2007-09-23 John Sullivan * planner.el (planner-copy-or-move-region): Use convenience functions instead of ELT and regexps. Don't include the task at the beginning of the region if point is at the end of the line, but do include it otherwise. Correct docstring to reflect actual behavior. 2007-09-21 Michael Olson * planner.el (planner-annotation-as-kill): Fix error that occurred when no annotation is found, and display a relevant message. 2007-09-17 John Sullivan * planner-tasks-overview.el (planner-tasks-overview-show-summary), (planner-tasks-overview-insert): Replace obsolete `planner-directory'. 2007-09-09 John Sullivan * planner-tasks-overview.el (planner-tasks-overview): Use planner-extract-tasks. (planner-tasks-overview-insert): Expect list layout returned by planner-extract-tasks, and use parsing functions. Improve display. Set working directory so that links work. Don't switch to planner-mode, stay in planner-tasks-overview-mode. (planner-tasks-overview-extract-all-tasks): Deleted because it's redundant; we use planner-extract-tasks for this. (planner-tasks-overview-mode): Derive from planner-mode, not fundamental-mode. (planner-tasks-overview-sort-by-date): Fix field number. (planner-tasks-overview-sort-by-plan): Fix field number. (planner-tasks-overview-sort-by-priority): Fix field number. (planner-tasks-overview-sort-by-field): Handle nil properly for sorting. (planner-tasks-overview-sort-by-status): Fix field numbers. * planner.el: Standardize and update compatibility info across all files. * planner-el.texi (Using Allout Mode): Minor doc fixes. 2007-08-30 John Sullivan * planner.el (planner-goto-hook): It's only run for day pages. 2007-08-29 John Sullivan * planner-registry.el (planner-registry-get-link-keywords): Use it. (planner-registry-get-keywords): Here too. * planner.el (planner-split-string): Compatibility hack for changes made in Emacs 22. * planner.el (planner-delete-task): Use it. * planner.el (planner-delete-task-hook): New hook. Thanks to David Vazquez for the suggestion. * planner-el.texi (Annotations): Remove misleadingly incomplete sentence describing default annotations. * planner.el (planner-annotation-from-man): New. Closes #8197 and #8196. (planner-annotation-from-woman): New. Thanks to Valery V. Vorotyntsev for getting both of these started. 2007-08-22 Michael Olson * planner-publish.el (planner-publish-diary-section-tag): Insert newline so that we avoid a validation error. 2007-08-19 Michael Olson * planner.el: Remove use of eval-when-compile in require statements, since it breaks compiled code. Also, emacs21 needs to require 'derived. 2007-07-21 Michael Olson * README: Mention that Muse 3.03 or later is needed. * planner-authz.el, planner-timeclock.el, planner-calendar.el, planner-publish.el: Remove support for old markup-tag syntax, now that Muse 3.03 is released. * planner-calendar.el (planner-calendar-prev-month-href) (planner-calendar-next-month-href): Don't escape specials specials in the URL description. This should fix a bug with "«" and "»". * planner-publish.el: Error out when loading if we have Muse less than 3.03. Also, remove `unless' wrapper around uses of muse-derive-style. (planner-publish-ignore-url-desc-specials): New variable that determines whether to ignore specials in URL descriptions. (planner-publish-decide-specials): New function that uses this variable. ("planner-xml", "planner-xhtml", "planner-xhtml"): Set :specials to planner-publish-decide-specials. * planner-el.texi: Replace "www.mwolson.org" with "mwolson.org" for brevity. 2007-07-03 Michael Olson * Makefile: Update debian package-building rules. 2007-06-17 Michael Olson * planner-publish.el (planner-publish-markup-regexps): Use group of planner-publish, rather than muse-html. 2007-05-26 Michael Olson * planner-el.texi (Installing from Arch): Update Archzoom URL. 2007-05-07 Michael Olson * README: Mention that there are multiple mailing lists. * planner-el.texi (Getting Help): Add entry for the new log messages list. * planner-publish.el: Fix bug in publishing of calendars. The finalization was happening before the header and footer were inserted, which was incorrect. 2007-04-09 Michael Olson * README: Use new link to online documentation. 2007-04-08 Michael Olson * planner*.el: Replace plannerlove website with maintainer's website. Closes #8847. * README: Mention maintainer's Planner page. Remove plannerlove. 2007-04-03 John Sullivan * planner-el.texi (Wanderlust): Update keybinding. * planner-wl.el (planner-wl-insinuate): Change keybinding to C-c C-t, closes #8361. 2007-04-03 Michael Olson * planner-el.texi (Preface): Use John's on-line documentation for Planner, rather than mine. 2007-04-02 John Sullivan * planner-el.texi (Planning based on the Franklin-Covey Approach): Correct MixedCase instructions, closes #8357. Other minor fixups too. 2007-03-04 John Sullivan * planner-el.texi (Installation): Mention what versions of emacsen we're compatible with. 2007-02-10 Michael Olson * planner.el (planner-setup-highlighting): Use quote instead of backquote. This should hopefully fix a weird error with ntemacs 23.0.0.1. 2007-02-06 John Sullivan * planner-el.texi (Task Detail): Clarification, see #8366. (Diary): We only bind a key in one of the two diary integration methods. Closes #8359. 2007-01-26 John Sullivan * planner-el.texi (Diary): Clarify that editing the diary section on a planner page does not affect the diary file. 2007-01-24 John Sullivan * planner-el.texi (Diary): Attach function name to keybinding description. 2007-01-14 John Sullivan * planner-gnus.el: Fix typo and change URL. (planner-gnus-browse-url): Make it work in NoGnus and Gnus 5.11, as suggested by Leo. 2007-01-14 Michael Olson * planner.el: Make sure various planner-annotation functions show up in the customize interface for `planner-annotation-functions'. Thanks to Hadron Quark for the report. * planner-el.texi (Installing from a Source Archive): Mention creating an ~/elisp directory. Also mention how to get Muse and Remember. Mention running "make clean". (Installing from Arch): Document Remember archive usage. Use "tla update", not "tla replay". (Installing from Debian): Mention remember-el. Since I get asked this so frequently, mention how to make the warning message go away -- it's not an error! (Timeclock): Shift xref to end of sentence so makeinfo doesn't complain. (Getting Help): Change URL to the emacswiki.org one. So long, plannerlove. Thanks to Hadron Quark for pointing all this out. (Tasks): Clarify wording of `C-c C-c' explanation. 2007-01-07 John Sullivan * Remove erroneously committed ChangeLog entries. * planner.el (planner-visit-link): We weren't passing the other-window argument to muse. Thanks to Wanrong Lin for noticing. 2007-01-05 John Sullivan * planner-timeclock.el (planner-schedule): Remove unnecessary dependency. * planner-el.texi (Timeclock): Fix typos. 2006-12-26 Michael Olson * planner-publish.el: Associate finalize function with :before-end, rather than :after. That way, if Planner files are included in another file by means of Muse's new tag, these transforms will still be applied. 2006-11-29 Michael Olson * planner-publish.el (planner-publish-note-tag): Don't call planner-replace-regexp-in-string if either the text or the regexp are empty strings. This should fix a bug with note publishing that XEmacs users were experiencing. Thanks to Cumhur Erkut for the report. 2006-11-04 John Sullivan * planner-el.texi (PSVN): Document all options and dependencies. (Hyperlinks): Reference Muse hyperlink syntax. * planner.el (planner-search-notes-internal): Provide a full path to the search results. Thanks to Michael Randall for reporting the bug. (planner-search-notes): Adjust display for new results return format. * planner-mhe.el: Remove unnecessary require. 2006-10-20 Michael Olson * planner-calendar.el: Adapt for nested tag support. Thanks to Charles philip Chan for noticing. 2006-10-16 Adrian Aichner * timeclock.el: Typo fixes. * timeclock.el (timeclock-history): New. * timeclock.el (timeclock-use-history): New. * timeclock.el (timeclock-log): Honor timeclock-use-history. * timeclock.el (timeclock-read-moment): Provide error on unexpected data in timeclock-file, going unnoticed until now. * timeclock.el (timeclock-find-discrep): Report line number of discrepancy to ease manual fixing. 2006-10-16 Michael Olson * planner-authz.el (planner-authz-markup-tags): Adapt for nested tag support. * planner-notes-index.el: Use add-hook instead of add-to-list, in case muse-publish has not been loaded yet. Use muse-publish-markup-tags instead of planner-markup-tags. * planner-publish.el (planner-publish-markup-tags): Adapt for nested tag support. Make the tag nestable. * planner-timeclock.el: Use add-hook instead of add-to-list, in case muse-publish has not been loaded yet. Use muse-publish-markup-tags and muse-colors-markup-tags instead of planner-markup-tags. (planner-colors-timeclock-report-tag) (planner-publish-timeclock-report-tag): New functions created from planner-timeclock-report-tag. 2006-09-26 Michael Olson * planner.el (planner-setup-highlighting): Don't quote beginning-of-line. This should fix a bug that was noticed in recent Emacs 22 builds. 2006-09-23 John Sullivan * planner-el.texi (Installing from Arch): Fix arch revision number. 2006-09-10 Michael Olson * planner-zoom.el (planner-zoom-iup, planner-zoom-idown) (planner-zoom-inext, planner-zoom-iprev): Use planner-page-name instead of buffer-name. This fixes a match-string error, and makes things work when you have muse-file-extension set to something. 2006-09-04 John Sullivan * planner.el (planner-list-tasks-with-status): Fix doc string. 2006-08-26 John Sullivan * planner-el.texi (Publishing Planner pages): Clarify the requirements and remove redundancies. (Notes): Update and clarify information about remember-planner. 2006-08-22 Magnus Henoch * planner-gnus.el (planner-gnus-browse-url): Fix marking unread messages as read problem. 2006-08-20 John Sullivan * planner-el.texi (Concept Index): Standardize and add missing module filenames as index entries. 2006-08-18 Marko Schütz * planner-timeclock-summary-proj.el (planner-timeclock-proj-entries): Fix bug that occurred when a timeclock entry had no project name. 2006-08-12 Michael Olson * Makefile (.PHONY): Split long line. * AUTHORS: Bookkeeping. * contrib/schedule.el: Update header. * contrib/timeclock.el: Install Adrian's changes from 2006-08-01. Note that this version of the file is not distributed with GNU Emacs, but with Planner instead. 2006-08-11 Michael Olson * planner-calendar.el (planner-calendar-published-file-href): Fix potential error when the calendar for next month is empty. 2006-08-08 Michael Olson * ChangeLog.1: Rename from ChangeLog.2004 to comply with standards in the Emacs source tree. * ChangeLog.2: Rename from ChangeLog.2005 to comply with standards in the Emacs source tree. * ChangeLog.3: New file created from the old ChangeLog. 2006-08-01 Adrian Aichner * timeclock.el: Keep timeclock-file buffer around, so that an encrypted timeclock-file does not have to be opened on each clocking operation (requiring entry of encryption key). * timeclock.el (timeclock-get-timeclock-file-buffer): New. * timeclock.el (timeclock-log): Don't kill timeclock-file buffer. * timeclock.el (timeclock-log-data): Use `timeclock-get-timeclock-file-buffer', which avoids reading timeclock-file, if it's already in a live buffer. * timeclock.el (timeclock-find-discrep): Ditto. * timeclock.el (timeclock-visit-timelog): Ditto. See ChangeLog.3 for earlier changes. ;; Local Variables: ;; coding: utf-8 ;; End: planner-el/ChangeLog.1000066400000000000000000005554651226462314700150570ustar00rootroot000000000000002004-12-27 05:27:14 GMT Sacha Chua patch-267 Summary: Bugfix: planner-align-tasks CVSism Revision: planner--dev--1.0--patch-267 * planner.el (planner-align-tasks): Ugly hack to get around the fact that ?\s is a CVSism. Thanks to Dryice Liu for reporting this modified files: ChangeLog planner.el 2004-12-27 03:48:28 GMT Sacha Chua patch-266 Summary: Fix typo in planner-find-file Revision: planner--dev--1.0--patch-266 modified files: ChangeLog planner.el 2004-12-27 02:34:09 GMT Sacha Chua patch-265 Summary: planner-sort-tasks: Sort unnumbered tasks as well Revision: planner--dev--1.0--patch-265 * planner.el (planner-sort-tasks): Make sort tasks behave without task numbers. modified files: ChangeLog planner.el 2004-12-27 02:25:13 GMT Sacha Chua patch-264 Summary: planner-renumber-tasks-automatically should be nil by default Revision: planner--dev--1.0--patch-264 * planner.el (planner-renumber-tasks-automatically): Set to nil by default now that we're encouraging not having task numbers... modified files: ChangeLog planner.el 2004-12-27 02:22:09 GMT Sacha Chua patch-263 Summary: planner-align-tasks: Behave even without task numbers Revision: planner--dev--1.0--patch-263 * planner.el (planner-align-tasks): Make align task behave even without task numbers. modified files: ChangeLog planner.el 2004-12-27 01:54:58 GMT Sacha Chua patch-262 Summary: New option: planner-default-task-status Revision: planner--dev--1.0--patch-262 * planner.el (planner-default-task-status): New option. Thanks to Dirk Bernhardt for patch. (planner-create-task-from-buffer): Add status argument. (planner-create-task): Add status argument. modified files: ChangeLog planner.el 2004-12-27 01:48:46 GMT Sacha Chua patch-261 Summary: Ugly bugfix for planner-find-file Revision: planner--dev--1.0--patch-261 modified files: ChangeLog planner.el 2004-12-27 01:19:27 GMT Sacha Chua patch-260 Summary: Set planner-use-task-numbers to nil by default Revision: planner--dev--1.0--patch-260 * planner.el (planner-use-task-numbers): Set to nil by default. Less visual clutter, less confusion. modified files: ChangeLog planner.el 2004-12-27 00:50:39 GMT Sacha Chua patch-259 Summary: planner-timeclock: Update entries when tasks are edited Revision: planner--dev--1.0--patch-259 * planner-timeclock.el: Automatically update timelog entries when a task is edited. (planner-replan-task): Merge from my config. (planner-edit-task-description): Merge from my config. modified files: ChangeLog planner-timeclock.el 2004-12-27 00:46:47 GMT Sacha Chua patch-258 Summary: Merge docfix from John Sullivan Revision: planner--dev--1.0--patch-258 2004-12-22 John Sullivan * planner.texi (Creating a Task): Removed redundant explanation of functions used to create tasks of different priorities. Added xref to Task Priorities section instead. (Task Priorities): Moved note about defining the default task priority to this section. (Planner Features): Moved Accomplishments, Task Overviews, Task IDs and Cyclic Tasks to the Task section of the manual. modified files: ChangeLog planner.texi 2004-12-27 00:23:23 GMT Sacha Chua patch-257 Summary: Odd; where did that \* Tasks come from? Revision: planner--dev--1.0--patch-257 modified files: ChangeLog planner.el 2004-12-26 23:09:30 GMT Sacha Chua patch-256 Summary: Major bugfix: planner-find-file Revision: planner--dev--1.0--patch-256 modified files: ChangeLog planner.el 2004-12-26 11:29:08 GMT Sacha Chua patch-255 Summary: Minor: Make planner-find-file an alias of emacs-wiki-find-file Revision: planner--dev--1.0--patch-255 * planner.el (planner-find-file): Revert to alias of emacs-wiki-find-file. Thanks to Wei-Hao Lin for pointing this out. modified files: ChangeLog planner.el 2004-12-25 01:46:47 GMT Sacha Chua patch-254 Summary: New: planner-dates-relative-to-today-flag Revision: planner--dev--1.0--patch-254 * planner.el (planner-dates-relative-to-today-flag): New. Thanks to John Sullivan for the suggestion. (planner-expand-name): Use planner-dates-relative-to-today. (planner-read-date): Keep track of base buffer and expand relative to that. modified files: ChangeLog planner.el 2004-12-24 15:27:48 GMT Sacha Chua patch-253 Summary: planner-multi.el: pass checkdoc Revision: planner--dev--1.0--patch-253 modified files: ChangeLog planner-multi.el 2004-12-24 15:23:04 GMT Sacha Chua patch-252 Summary: planner-multi.el: New Revision: planner--dev--1.0--patch-252 * planner-multi.el: New support for notes on multiple pages. Thanks to Dryice Liu for the inspiration. new files: .arch-ids/planner-multi.el.id planner-multi.el modified files: ChangeLog planner-timeclock.el planner.el 2004-12-24 10:08:30 GMT Sacha Chua patch-251 Summary: planner-timeclock-summary: Allow functions as filters Revision: planner--dev--1.0--patch-251 * planner-timeclock-summary.el: (planner-timeclock-summary-day-range-entry): Allow functions as filters. (planner-timeclock-summary-make-summary-string-range, (planner-timeclock-summary-calculate-ratio-day, (planner-timeclock-summary-make-text-table-day, (planner-timeclock-summary-show-filter, (planner-timeclock-summary-show-range-filter, (planner-timeclock-summary-show-range): Docfix. modified files: ChangeLog planner-timeclock-summary.el planner.texi 2004-12-23 08:11:54 GMT Sacha Chua patch-250 Summary: Docfix: Correct Stefan Reichör's e-mail address. Revision: planner--dev--1.0--patch-250 * planner.el: Correct Stefan Reichör's e-mail address. modified files: ChangeLog planner.el 2004-12-22 13:34:04 GMT Sacha Chua patch-249 Summary: planner-deadline: Don't update completed or cancelled tasks. New: planner-deadline-change Revision: planner--dev--1.0--patch-249 * planner-deadline.el: Merge patch from Dryice Liu. (planner-deadline-regexp): Document regexp group format. (planner-deadline-update): Document regexp and default. Patch from Dryice: Don't update completed or cancelled tasks. (planner-deadline-change): New function for convenience. * planner.texi (Deadlines): Document planner-deadline.el. modified files: ChangeLog planner-deadline.el planner.texi 2004-12-21 13:24:42 GMT Sacha Chua patch-248 Summary: New: planner-timeclock-summary-proj.el Revision: planner--dev--1.0--patch-248 * planner-timeclock-summary-proj.el: New from Pascal Quesseveur. Add copyright notice. Make it pass checkdoc and byte-compile. * planner.texi (Timeclock): Add sample for planner-timeclock-summary. Document planner-timeclock-summary-proj. new files: .arch-ids/planner-timeclock-summary-proj.el.id planner-timeclock-summary-proj.el modified files: ChangeLog planner.texi 2004-12-20 23:19:08 GMT Sacha Chua patch-247 Summary: Docfix from John Sullivan: Components Revision: planner--dev--1.0--patch-247 * planner.texi (Components): Cleaned up redundancies and streamlined the explanation of what's in the archive. modified files: ChangeLog planner.texi 2004-12-20 14:22:47 GMT Sacha Chua patch-246 Summary: Docfix: Typo in sample configuration Revision: planner--dev--1.0--patch-246 * planner.texi (Sacha Chua's Configuration): Minor typo. modified files: ChangeLog planner.texi 2004-12-20 10:19:03 GMT Sacha Chua patch-245 Summary: Docfix: Move thoughts to first part, update my config Revision: planner--dev--1.0--patch-245 * planner.texi (Stable Version): Add note about arch. (Development Version): Update emacs-wiki instructions. Use mwolson's repository. (Advanced Installation): Add note about remember. (Thoughts): Move to first part of info file. (Why Use PlannerMode): Update. (Sample Configuration Files): Include example configuration. (Sacha Chua's Configuration): Comment and update. modified files: ChangeLog planner.texi 2004-12-20 09:07:22 GMT Sacha Chua patch-244 Summary: Docfixes from John Sullivan Revision: planner--dev--1.0--patch-244 Changelog from John Sullivan; thanks for the patch! * planner.texi (Preface): Added xref to Acknowledgements. (Components): Moved bit about the relationship with EmacsWikiMode to hear from the Introduction. (Introduction): Fleshed out and organized the writing a bit, trying to give a better idea of what to expect and how to proceed. (Stable Version): Reorganized install information to cut down on redunancies, improve flow, and make everything specific to stable version. (Development Version): Did the same for the development version. Moved extra arch information to the bottom of the section. Thinking about consolidating arch information in its own separate section. (Acknowledgements): Moved maintainer timeline here, renamed the chapter to Maintainers and Contributors. modified files: ChangeLog planner.texi 2004-12-17 11:39:40 GMT Sacha Chua patch-243 Summary: planner-timeclock-summary: Alias time-subtract if necessary Revision: planner--dev--1.0--patch-243 * planner-timeclock-summary.el (time-date): Alias time-subtract. modified files: ChangeLog planner-timeclock-summary.el 2004-12-17 11:12:28 GMT Sacha Chua patch-242 Summary: planner-timeclock-summary: Requite time-date Revision: planner--dev--1.0--patch-242 * planner-timeclock-summary.el (time-date): Require time-date. Thanks to David Lord for pointing this out. modified files: ChangeLog planner-timeclock-summary.el 2004-12-17 11:08:29 GMT Sacha Chua patch-241 Summary: Minor fix: add space after author name on newsgroups Revision: planner--dev--1.0--patch-241 * planner-gnus.el: Add space after author name on newsgroups. Thanks to Magnus Henoch for the patch. (planner-gnus-annotation-from-summary): Add space. (planner-gnus-annotation-from-message): Add space. modified files: ChangeLog planner-gnus.el 2004-12-17 10:58:04 GMT Sacha Chua patch-240 Summary: planner-timeclock-summary: plan pages, filtering, checkdoc, byte-compile Revision: planner--dev--1.0--patch-240 * planner-timeclock-summary.el: Extensive reordering and docfixing to satisfy checkdoc and byte-compile-file. (planner-timeclock-summary-day-range-entry): Rename from planner-timeclock-day-range-entry to fit namespace. (planner-timeclock-summary-one-day-alist): Rename from planner-timeclock-one-day-alist to fit namespace. (planner-timeclock-summary-one-day-entry-no-date): Rename from planner-timeclock-one-day-entry-no-date to fit namespace. (planner-timeclock-summary-one-day-entry): Rename from planner-timeclock-one-day-entry to fit namespace. (planner-timeclock-summary-day-range-alist): Rename from planner-timeclock-day-range-alist to fit namespace. (planner-timeclock-within-date-range): Exploit the string nature for dates. * planner-timeclock-summary.el: Merge patch from Chris Parsons allowing filtering by regexp on the task string. Also support automatic updating of a Timeclock section in the plan page. (planner-timeclock-summary-include-sub-plan-pages-flag): New option. Note: renamed from planner-timeclock-summary-include-sub-plan-pages in original patch. (planner-timeclock-summary-update): Add support for plan pages. (planner-timeclock-summary-show-filter): New. (planner-timeclock-summary-show-range-filter): New. (planner-timeclock-summary-show-range): Add filter-regexp. (planner-timeclock-summary-calculate-ratio-day): Add filter-regexp. (planner-timeclock-summary-make-text-table-day): Add filter-regexp and hide-summary. (planner-timeclock-summary-make-summary-string-range): Add filter-regexp. (planner-timeclock-day-range-entry): Add filter-regexp. modified files: ChangeLog planner-timeclock-summary.el 2004-12-17 09:26:54 GMT Sacha Chua patch-239 Summary: Move index formatting code into planner.el Revision: planner--dev--1.0--patch-239 * planner.el (planner-index): Moved from planner-experimental.el. Thanks to David Lord for the vote of confidence. (planner-generate-index): Moved from planner-experimental.el (emacs-wiki-generate-index): Advise this function so that planner pages get a planner-style index. * planner-experimental.el: Remove index code. modified files: ChangeLog planner-experimental.el planner.el 2004-12-17 09:10:31 GMT Sacha Chua patch-238 Summary: New: planner-bookmark Revision: planner--dev--1.0--patch-238 * planner-bookmark.el: New from Dryice Liu. Requires remember. Creates a note buffer with a bookmark:// URL after you set a bookmark. * planner-auto.el: Add planner-bookmark.el * planner.texi (planner-bookmark.el): Document planner-bookmark.el new files: .arch-ids/planner-bookmark.el.id planner-bookmark.el modified files: ChangeLog planner-auto.el planner.texi 2004-12-17 04:23:24 GMT Sacha Chua patch-237 Summary: planner-default-task-priority: New default "B" Revision: planner--dev--1.0--patch-237 * planner.el (planner-default-task-priority): Change default to "B". "A" tasks are intimidating, and "B" is easier to adjust upward or downward. modified files: ChangeLog planner.el 2004-12-16 09:26:47 GMT Sacha Chua patch-236 Summary: Add copyright notices Revision: planner--dev--1.0--patch-236 modified files: ChangeLog planner-diary.el planner-gnus.el planner-log-edit.el planner-timeclock-summary.el planner.el 2004-12-15 13:54:06 GMT Sacha Chua patch-235 Summary: Bugfix: planner-timeclock-summary-make-summary-string-range Revision: planner--dev--1.0--patch-235 * planner-timeclock-summary.el: Merge patch from Dryice Liu. (planner-timeclock-summary-make-summary-string-range): Should work as documented. String replace now case-sensitive. modified files: ChangeLog planner-timeclock-summary.el 2004-12-15 13:35:01 GMT Sacha Chua patch-234 Summary: New: planner-timeclock-summary-show-range Revision: planner--dev--1.0--patch-234 * planner-timeclock-summary.el: Merge patch from Chris Parsons allowing date ranges when summarizing data. Many functions now have range arguments. (planner-timeclock-summary-show-range): New user function. modified files: ChangeLog planner-timeclock-summary.el 2004-12-15 04:03:47 GMT Sacha Chua patch-233 Summary: planner-rss-add-note: Remove trailing tag from titles Revision: planner--dev--1.0--patch-233 * planner-rss.el (planner-rss-add-note): Remove new emacs-wiki rule for paragraphs so that titles don't have trailing paragraph end tags. Thanks to jan for pointing it out. modified files: ChangeLog planner-rss.el 2004-12-15 04:02:19 GMT Sacha Chua patch-232 Summary: Bugfix: planner-mark-task Emacs CVS-ism Revision: planner--dev--1.0--patch-232 * planner.el (planner-mark-task): Fix Emacs CVS-ism in skip-chars-forward. Thanks to John Sullivan for pointing it out. modified files: ChangeLog planner.el 2004-12-14 03:44:26 GMT Sacha Chua patch-231 Summary: planner-mark-task: Minimize buffer editing Revision: planner--dev--1.0--patch-231 * planner.el (planner-mark-task): Minimize buffer editing and make save-excursion work. modified files: ChangeLog planner.el 2004-12-13 23:56:59 GMT Sacha Chua patch-230 Summary: planner-log-edit-quote-filenames-flag: New Revision: planner--dev--1.0--patch-230 * planner-log-edit.el: Merge and edit Dryice Liu's patch for quoting filenames. (planner-log-edit-quote-filenames-flag): New. Renamed from planner-log-edit-quote-filenames in original patch in order to pass checkdoc. (planner-log-edit-quote-file-maybe): Changed implementation and removed helper function. (planner-log-edit-add-note): Guard against nil. modified files: ChangeLog planner-log-edit.el 2004-12-11 15:37:25 GMT Sacha Chua patch-229 Summary: Docfix: planner.texi Revision: planner--dev--1.0--patch-229 * planner.texi: Thanks to mocker for proofreading. (Development Version): Add note about require. (Overview): Fix example code for keybinding. modified files: ChangeLog planner.texi 2004-12-11 08:00:52 GMT Sacha Chua patch-228 Summary: planner-gnus-browse-url: use gnus-registry if loaded Revision: planner--dev--1.0--patch-228 * planner-gnus.el (planner-gnus-browse-url): Merge Sven Kloppenburg's code to use the Gnus registry. Modify patch so that it works even if the registry fails. modified files: ChangeLog planner-gnus.el 2004-12-11 07:58:26 GMT Sacha Chua patch-227 Summary: planner-notes-tag: Work with new emacs-wiki Revision: planner--dev--1.0--patch-227 * planner.el (planner-notes-tag): Bugfix: Add page name so that this works with the new emacs-wiki which doesn't recognize links of the form [[#1][...]]. modified files: ChangeLog planner.el 2004-12-10 22:47:26 GMT Sacha Chua patch-226 Summary: planner-report update from ajk Revision: planner--dev--1.0--patch-226 * planner-report.el: Merge update from ajk. From ajk: Fix bugs that caused some tasks and notes to be left out. Remove redundant code. (planner-report-remove-tasks-numbers): New customization option planner-report-remove-task-numbers enables removal of task priority numbers in status reports (they don't increment per-project and therefore don't mean much). (planner-report-replace-note-numbers): New customization option planner-report-replace-note-numbers enables replacement of note numbers (again, they don't mean much in a status report) with some string (defaults to "**"). (planner-report-unfinished-offset): New customization option planner-report-unfinished-offset specifies the number of days from the current date of unfinished tasks to include in the status report. Before, all unfinished tasks were included. modified files: ChangeLog planner-report.el 2004-12-09 14:48:17 GMT Sacha Chua patch-225 Summary: planner-deadline.el: Remove hook Revision: planner--dev--1.0--patch-225 * planner-deadline.el: Remove hook. modified files: ChangeLog planner-deadline.el 2004-12-08 10:32:48 GMT Sacha Chua patch-224 Summary: planner-deadline: Preliminary implementation Revision: planner--dev--1.0--patch-224 * planner-deadline.el: Preliminary implementation. Rewrites tasks with deadline information. new files: .arch-ids/planner-deadline.el.id planner-deadline.el modified files: ChangeLog 2004-12-06 13:12:56 GMT Sacha Chua patch-223 Summary: New: Make planner-sort-tasks-key-function pluggable Revision: planner--dev--1.0--patch-223 * planner.el (planner-sort-tasks-key-function): New. Thanks to Jody Klymak and John Sullivan for finally prompting me to do this. (planner-on-date-page): New. (planner-sort-tasks-default-key): New. (planner-sort-tasks-basic): New. (planner-sort-tasks-by-date): New. (planner-sort-tasks-by-link): New. (planner-sort-tasks): Use new planner-sort-tasks-key-function. modified files: ChangeLog planner.el planner.texi 2004-12-04 05:44:18 GMT Sacha Chua patch-222 Summary: planner-create-note: Make chronological notes neater Revision: planner--dev--1.0--patch-222 * planner.el (planner-create-note): Add extra newline before created notes so that chronological notes look neat. modified files: ChangeLog planner-log-edit.el planner.el 2004-12-03 09:18:26 GMT Sacha Chua patch-221 Summary: Add changelog to arch repository. Thanks to mwolson for tip. Revision: planner--dev--1.0--patch-221 new files: .arch-ids/ChangeLog.id ChangeLog 2004-12-03 03:59:23 GMT Sacha Chua patch-220 Summary: planner-lower-task: Last-task bugfix Revision: planner--dev--1.0--patch-220 * planner.el (planner-raise-task): Split planner-lower-task so that the code is clearer. (planner-lower-task): Redo functionality. Fix last-task bug reported by Jonathan Hankins. * planner.texi (Changing Tasks): Document changes to planner-raise-task and planner-lower-task. modified files: planner.el planner.texi 2004-12-02 13:53:08 GMT Sacha Chua patch-219 Summary: planner-extract-tasks bugfix: use planner project Revision: planner--dev--1.0--patch-219 * planner.el (planner-extract-tasks): Bugfix: wrap in planner project. This solves the problem with emacs-wiki-name-regexp not recognizing dates. Other functions that use temporary buffers or calculate planner data outside a planner buffer should do that also. modified files: planner.el 2004-12-02 04:18:23 GMT Sacha Chua patch-218 Summary: planner-tasks-overview-show-summary: plan page overview Revision: planner--dev--1.0--patch-218 * planner-tasks-overview.el (planner-tasks-overview-show-summary): New. Provides an overview of unfinished (scheduled/unscheduled) and completed tasks in (plan) pages. (planner-tasks-overview-get-summary): New. modified files: planner-tasks-overview.el 2004-12-01 10:24:12 GMT Sacha Chua patch-217 Summary: planner-timeclock, planner-task-in-progress: Always use plan Revision: planner--dev--1.0--patch-217 * planner-timeclock.el (planner-task-in-progress): Minor tweak to always get the project plan if available. modified files: planner-timeclock.el 2004-12-01 09:50:11 GMT Sacha Chua patch-216 Summary: planner-create-note-from-task: Follow original patch Revision: planner--dev--1.0--patch-216 * planner.el (planner-create-note-from-task): Come to think of it, Chris' way of checking date-ness is better than mine. Silly maintainer alert! How embarrassing. modified files: planner.el 2004-12-01 09:45:10 GMT Sacha Chua patch-215 Summary: planner-create-note-from-task: C-u means put note on plan page Revision: planner--dev--1.0--patch-215 * planner.el (planner-create-note-from-task): Merge Chris Parsons' tweak: prefix argument means put note on plan page. modified files: planner.el 2004-11-30 07:56:41 GMT Sacha Chua patch-214 Summary: planner-update-task: Allow more flexible planner-jump-to-linked-task Revision: planner--dev--1.0--patch-214 * planner.el (planner-update-task): Move local page checking code in so that planner-jump-to-linked-task can easily be modified. modified files: planner.el 2004-11-29 23:18:13 GMT Sacha Chua patch-213 Summary: Bugfix: planner-gnus-browse-url: Remove Emacs CVS-ism in split-string Revision: planner--dev--1.0--patch-213 * planner-gnus.el (planner-gnus-browse-url): Remove Emacs CVS-ism (split-string with three arguments). Thanks to Dryice Liu for the bug report. modified files: planner-gnus.el 2004-11-27 07:27:42 GMT Sacha Chua patch-212 Summary: Clean up bytecompiling errors Revision: planner--dev--1.0--patch-212 * planner-calendar.el (planner-calendar-date-to-filename): Move before first call. * planner-timeclock-summary.el (planner-timeclock-summary-generate-report): Add let bindings for free variables project-name and task-name. (planner-timeclock-summary-make-table-day): Fix typo in defun. * planner-gnus.el (planner-gnus-annotation-from-summary): Fix bug; free variable `from'. modified files: planner-calendar.el planner-gnus.el planner-timeclock-summary.el 2004-11-27 07:04:54 GMT Sacha Chua patch-211 Summary: New: planner-task-open Revision: planner--dev--1.0--patch-211 * planner.el: Implement Dirk Bernhardt's planner-task-open. (planner-task-open): New. (planner-menu): Add planner-task-open. * planner.texi (Changing Tasks): Document planner-task-open. modified files: planner.el planner.texi 2004-11-27 06:53:13 GMT Sacha Chua patch-210 Summary: New: planner-timeclock-summary.el Revision: planner--dev--1.0--patch-210 * planner-timeclock-summary.el: New from Dryice Liu. * planner.texi (Timeclock): Note about planner-timeclock-summary.el . new files: .arch-ids/planner-timeclock-summary.el.id planner-timeclock-summary.el modified files: planner.texi 2004-11-27 06:47:26 GMT Sacha Chua patch-209 Summary: New: planner-rdf.el from Rainer Volz Revision: planner--dev--1.0--patch-209 * planner-rdf.el: New from Rainer Volz (http://www.rainervolz.de/planner-rdf/). * planner-rdf.owl: New. * planner.texi (RDF Publication): Copy and texinfo-ize documentation. new files: .arch-ids/planner-rdf.el.id .arch-ids/planner-rdf.owl.id planner-rdf.el planner-rdf.owl modified files: planner.texi 2004-11-27 06:19:53 GMT Sacha Chua patch-208 Summary: New: planner-report.el Revision: planner--dev--1.0--patch-208 * planner-report.el: New. new files: .arch-ids/planner-report.el.id planner-report.el 2004-11-27 05:55:08 GMT Sacha Chua patch-207 Summary: New: planner-create-note-from-task Revision: planner--dev--1.0--patch-207 * planner.el (planner-create-note-from-task): New. * planner.texi (Notes): Document planner-create-note-from-task. modified files: planner.el planner.texi 2004-11-27 05:52:33 GMT Sacha Chua patch-206 Summary: planner.texi: Minor typo fix in "Making Files Pretty" Revision: planner--dev--1.0--patch-206 * planner.texi (Making Files Pretty): Fix typo reported by Carl Witty in Debian bug #282824. modified files: planner.texi 2004-11-27 05:49:55 GMT Sacha Chua patch-205 Summary: planner-diary.el: Typo fixes Revision: planner--dev--1.0--patch-205 * planner-diary.el: Thanks to Dryice Liu for pointing out typos. (planner-diary-update-section): Fix typo. (planner-diary-insert-appts): Fix typo. (planner-diary-insert-public): Fix typo. (planner-diary-insert-private): Fix typo. * planner-diary.el: Fix incorrect arguments passed to planner-filename-to-calendar-date so that file compiles cleanly. (planner-diary-appts-entries-here): Fix incorrect arguments. (planner-diary-cal-desk-entries-here): Fix incorrect arguments. (planner-diary-private-entries-here): Fix incorrect arguments. (planner-diary-public-entries-here): Fix incorrect arguments. modified files: planner-diary.el 2004-11-25 03:37:09 GMT Sacha Chua patch-204 Summary: planner.texi: Add pointer to online documentation Revision: planner--dev--1.0--patch-204 * planner.texi (Development Version): Add note about documentation. (Stable Version): Add note about documentation. modified files: planner.texi 2004-11-20 09:13:36 GMT Sacha Chua patch-203 Summary: Minor fix: Add planner-task-cancelled to menu Revision: planner--dev--1.0--patch-203 * planner.el (planner-menu): Add planner-task-cancelled. Thanks to Jody Klymak for pointing this out. modified files: planner.el 2004-11-20 06:26:18 GMT Sacha Chua patch-202 Summary: Bugfix: planner-gnus annotations from newsgroups Revision: planner--dev--1.0--patch-202 * planner-gnus.el: Thanks to Magnus Henoch for bugfix. (planner-gnus-annotation-from-summary): Consider newsgroups. (planner-gnus-annotation-from-message): Consider neswgroups. modified files: planner-gnus.el 2004-11-20 06:24:39 GMT Sacha Chua patch-201 Summary: Bugfix: emacs-wiki-unhighlight-region advice: zap overlays Revision: planner--dev--1.0--patch-201 * planner.el (emacs-wiki-unhighlight-region): New advice: zap planner overlays so that unhighlight-region really works. modified files: planner.el 2004-11-20 06:21:51 GMT Sacha Chua patch-200 Summary: planner-diary-create-section-flag Revision: planner--dev--1.0--patch-200 * planner-diary.el (planner-diary-create-section-flag): New. (planner-diary-update-section): Honor planner-diary-create-section-flag. * planner.texi (Diary): Document planner-diary-create-section-flag. modified files: planner-diary.el planner.texi 2004-11-19 14:08:34 GMT Sacha Chua patch-199 Summary: Docfix: Reorganized sample configuration Revision: planner--dev--1.0--patch-199 modified files: planner.texi 2004-11-14 14:00:55 GMT Sacha Chua patch-198 Summary: planner-gnus: Check if To: exists before using it Revision: planner--dev--1.0--patch-198 * planner-gnus.el: Thanks to Magnus Henoch for pointing out this bug. (planner-gnus-annotation-from-message): Make sure To: exists before using it. (planner-gnus-annotation-from-summary): Make sure To: exists before using it. modified files: planner-gnus.el 2004-11-08 13:52:39 GMT Sacha Chua patch-197 Summary: planner-markup-task: Make unfinished tasks behave Revision: planner--dev--1.0--patch-197 * planner.el (planner-markup-task): Use ajk's fix for the unfinished tasks markup bug. This prevents task underlines from matching markup underlines. modified files: planner.el 2004-11-06 03:21:39 GMT Sacha Chua patch-196 Summary: Change planner-menu labels for consistency Revision: planner--dev--1.0--patch-196 * planner.el (planner-menu): Change task menu entry labels according to Frederik Fouvry's suggestions. modified files: planner.el 2004-10-31 14:12:22 GMT Sacha Chua patch-195 Summary: New: planner-bibtex, planner-annotation-as-kill Revision: planner--dev--1.0--patch-195 * planner-bibtex.el: New. Thanks to James Clarke for the contribution. * planner.el (planner-annotation-as-kill): New. Thanks to James Clarke for the idea. * planner.texi (Overview): Add planner-annotation-as-kill. (planner-bibtex.el): New. new files: .arch-ids/planner-bibtex.el.id planner-bibtex.el modified files: planner-auto.el planner.el planner.texi 2004-10-31 12:41:37 GMT Sacha Chua patch-194 Summary: New: planner-auto.el. Docfix: Overview Revision: planner--dev--1.0--patch-194 * planner-auto.el: New. * planner.texi (Basic Configuration): Add note about planner-update-wiki-project. (Overview): New. Thanks to JC Helary for asking for an overview. new files: .arch-ids/planner-auto.el.id planner-auto.el modified files: planner.texi 2004-10-31 05:37:33 GMT Sacha Chua patch-193 Summary: planner-accomplishments-insinuate: Try different file hooks. Revision: planner--dev--1.0--patch-193 * planner-accomplishments.el (planner-accomplishments-insinuate): Try the different file hooks. Compatibility is hard. Thanks to Christopher San Diego for the bug report. modified files: planner-accomplishments.el 2004-10-31 05:35:35 GMT Sacha Chua patch-192 Summary: planner-gnus-browse-url: Bugfix: Make sure articles are loaded Revision: planner--dev--1.0--patch-192 * planner-gnus.el (planner-gnus-browse-url): Make sure the headers for all the mentioned articles have been loaded. This fixes the virtual article bug. modified files: planner-gnus.el 2004-10-24 12:53:01 GMT Sacha Chua patch-190 Summary: New: planner-log-edit.el Revision: planner--dev--1.0--patch-190 * planner-log-edit.el: New. Modifications from original: some name changes to satisfy checkdoc, new planner-log-edit-notice-commit-function. Thanks to Simon Winwood for new feature. * planner.texi (planner-log-edit.el): New. new files: .arch-ids/planner-log-edit.el.id planner-log-edit.el modified files: planner.texi 2004-10-24 12:08:06 GMT Sacha Chua patch-189 Summary: planner-create-task: Change "from" annotation to ":" Revision: planner--dev--1.0--patch-189 * planner.el (planner-create-task): Change annotation string to : so that the grammar isn't weird. Thanks to Richi Plana for pointing this out. modified files: planner.el 2004-10-23 08:39:52 GMT Sacha Chua patch-188 Summary: planner-gnus patch from kanaldrache: use process marks Revision: planner--dev--1.0--patch-188 * planner-gnus.el: Merge patch from Mario Domgörgen. (planner-gnus-get-message-id): Allow the use of article numbers. (planner-gnus-annotation-from-summary): Allow process marks. (planner-gnus-browse-url): Allow process marks. modified files: planner-gnus.el 2004-10-17 03:15:26 GMT Michael Olson patch-13 Summary: Attempt to fix problem where mode is not changed properly Revision: planner--mwolson--1.0--patch-13 2004-10-16 Michael Olson * planner.el (planner-mode): Explicitly check local variables to see if the user wants the current file to be in a different mode. Should fix problem with local variables being ignored as per which mode to use. modified files: planner.el 2004-10-14 04:24:41 GMT Michael Olson patch-11 Summary: Add copyright notices and note contributions Revision: planner--mwolson--1.0--patch-11 2004-10-13 Michael Olson * planner-bbdb.el: Make contributors section. Add Andrew J. Korty to it. * planner-diary.el: Make contributors section. Add Travis B. Hartwell to it. Space out years in copyright notice. Make spacing in header part of file more consistent. * planner-export-diary.el: Make contributors section. Add Xin Wei Hu to it. Add copyright notice for Xin Wei Hu. * planner-ledger.el: Add email address for Will Glozer to copyright notice. Remove spurious semicolons. * planner-rmail.el: Remove spurious semicolons. Make contributors section. Add Frederik Fouvry to it. * planner-tasks-overview.el: Reformat commentary section. Make contributors section. Add Andrew J. Korty to it. Add thanks section because the URL in it mentions someone who also helped out with this file in some way. * planner-vm.el: Add Parts copyright notice for Jürgen Doser. Add him also to the newly-made contributors section. * planner-wl.el: Add email address for Yvonne Thomson. Add Parts copyright notice for Angus Lees. Add him to the newly-made contributors section. Remove "Largely rehacked" message since the contributors section describes the contribution better. * planner.el: Change Parts copyright message for Sacha to a full copyright notice since she is the maintainer. Add Parts copyright notices for David D. Smith, Yvonne Thomson, Michael Olson, and Maciej Kalisak. Add more detail to thanks section. Add David D. Smith, Daniel Neri, Mario Peter, Yvonne Thomson, Hoan Ton-That, Michael Olson, Maciej Kalisak, Dale P. Smith, and Stefan Reichör to the newly-made contributors section. (planner-annotation-from-info): Move "Thanks to ..." notice to contributors section. modified files: planner-bbdb.el planner-diary.el planner-export-diary.el planner-ledger.el planner-rmail.el planner-tasks-overview.el planner-vm.el planner-wl.el planner.el 2004-10-13 13:07:07 GMT Sacha Chua patch-186 Summary: planner-gnus, summary: Take process marks into account Revision: planner--dev--1.0--patch-186 * planner-gnus.el (planner-gnus-annotation-from-summary): Take process marks into account. Thanks to Mario Domgörgen for the patch. 2004-10-09 10:22:42 GMT Sacha Chua patch-185 Summary: NEW: planner-notes-tag Revision: planner--dev--1.0--patch-185 * planner.el (planner-markup-tags): New tag: . Finally allows me to have blog headlines. (planner-notes-get-headlines): Move from planner-notes-index. (planner-notes-tag): New tag. * planner-notes-index.el (planner-notes-index-get-headlines): Rename to planner-notes-index-headlines-on-page because planner-notes-get-headlines refers to the current page. (planner-notes-index-get-headlines-range): Fix grammar. Rename to planner-notes-index-headlines-in-range. * planner.texi (Planner Tags): New. modified files: planner-notes-index.el planner.el planner.texi 2004-10-09 04:13:24 GMT Sacha Chua patch-184 Summary: planner-id-update-automatically should default to t Revision: planner--dev--1.0--patch-184 * planner-id.el (planner-id-update-automatically): Make the default t as people expect it to Just Work. Docfix: Mention planner-edit-task-description. Thanks to Niklas Morberg for pointing out that this is the reasonable default. * planner.texi (Task IDs): Note: planner-id-update-automatically now defaults to t. modified files: planner-id.el planner.texi 2004-10-06 09:22:43 GMT Sacha Chua patch-183 Summary: plan: Force planner-tasks-file-behavior to 'save if nil, honor 'close Revision: planner--dev--1.0--patch-183 * planner.el (plan): Force planner-tasks-file-behavior so that the file list can be updated. Fix buggy let binding of planner-tasks-file-behavior. Thanks to Yvonne for pointing this out. modified files: planner.el 2004-10-04 15:16:59 GMT Sacha Chua patch-182 Summary: Real bugfix for -maybe functions; other files were defining write-file-functions Revision: planner--dev--1.0--patch-182 * planner-id.el (planner-id-setup): Use local-write-file-hooks if write-file-functions is not available. Thanks to pll for patiently helping me debug. * planner-accomplishments.el (planner-accomplishments-insinuate): Use local-write-file-hooks if write-file-functions is not available. Thanks to pll for patiently helping me debug. modified files: planner-accomplishments.el planner-id.el 2004-10-04 14:51:34 GMT Sacha Chua patch-181 Summary: Bugfix: -maybe functions should not be defsubsts Revision: planner--dev--1.0--patch-181 * planner.el (planner-sort-tasks-maybe), (planner-renumber-tasks-maybe), (planner-renumber-notes-maybe), (planner-align-tasks-maybe): XEmacs doesn't like defsubsts for hooks, I think. modified files: planner.el 2004-10-04 14:10:50 GMT Sacha Chua patch-180 Summary: planner-find-file: Do not double-open pages Revision: planner--dev--1.0--patch-180 * planner.el (planner-find-file): Prevent double-opening pages by checking if the current buffer is already the page we want to open. modified files: planner.el 2004-10-02 04:59:21 GMT Sacha Chua patch-179 Summary: Docfix for planner-tasks-file-behavior Revision: planner--dev--1.0--patch-179 * planner.texi (Variables to Customize): Docfix for new default. modified files: planner.texi 2004-10-02 04:58:23 GMT Sacha Chua patch-178 Summary: Change planner-tasks-file-behavior default to nil Revision: planner--dev--1.0--patch-178 * planner.el (planner-tasks-file-behavior): Change default to nil. That way, we don't scare people with slow behavior. modified files: planner.el 2004-10-01 09:46:13 GMT Sacha Chua patch-177 Summary: planner-save-buffers: Turn off more things in attempt to solve infloop Revision: planner--dev--1.0--patch-177 * planner.el (planner-save-buffers): Turn off planner-id behavior, too. Save only modified buffers. Thanks to Stefan Reicho:r for the small patch. modified files: planner-tasks-overview.el planner.el 2004-09-30 11:10:40 GMT Sacha Chua patch-176 Summary: NOTE: Restore planner-diary-entries-here Revision: planner--dev--1.0--patch-176 * planner-diary.el (planner-diary-get-diary-entries): Restore lisp functionality. Prevent font-locking during planner-diary-entries-here, avoiding the infloop bug. modified files: planner-diary.el 2004-09-30 03:47:20 GMT Sacha Chua patch-175 Summary: Bugfix: Remove planner-diary-font-locking code Revision: planner--dev--1.0--patch-175 modified files: planner-diary.el 2004-09-29 14:49:52 GMT Sacha Chua patch-174 Summary: NOTE: planner-diary.el: Remove font-locking method Revision: planner--dev--1.0--patch-174 * planner-diary.el: After much bug-hunting, I have decided to remove the fontlocking code from the module as it causes too many headaches. If you want it back in, please send me a working patch. =) * planner.texi (Diary): Docfix: Remove mention of Lisp fontlocking feature. modified files: planner-diary.el 2004-09-29 13:57:30 GMT Sacha Chua patch-173 Summary: planner-diary.el: Fall back to using buffer name if file name is not available Revision: planner--dev--1.0--patch-173 * planner-diary.el (planner-diary-get-name): New. Pick up the filename if possible. Fall back to buffer name if not yet available. This works around a strange font-lock problem when the buffer filename is not yet available. Update many functions to use planner-diary-get-name. The lisp font-locking code should work again. modified files: planner-diary.el 2004-09-28 15:00:51 GMT Sacha Chua patch-172 Summary: planner-gnus-browse-url: Go back to the safer way of doing things Revision: planner--dev--1.0--patch-172 * planner-gnus.el (planner-gnus-browse-url): Go back to the somewhat safer (but more tedious) way of doing things. modified files: planner-gnus.el 2004-09-28 03:52:51 GMT Sacha Chua patch-171 Summary: planner-task-info-from-string: fix tasks that are not true wiki names Revision: planner--dev--1.0--patch-171 * planner.el (planner-task-info-from-string): Fix tasks that are not true wiki names. Thanks to Dale P. Smith for bug report and patch. modified files: planner.el 2004-09-24 10:03:45 GMT Sacha Chua patch-170 Summary: Minor XEmacs bugfix: Use planner-derived-mode-p instead of derived-mode-p Revision: planner--dev--1.0--patch-170 * planner.el (planner-create-task-from-buffer), (planner-create-task): Bugfix: Make XEmacs happy by using planner-derived-mode-p instead. * planner-accomplishments.el (planner-accomplishments-show): Bugfix: Make XEmacs happy by using planner-derived-mode-p instead. modified files: planner-accomplishments.el planner.el 2004-09-24 10:00:51 GMT Sacha Chua patch-169 Summary: planner-tasks-file-behavior tweaks: No more jumping cursor Revision: planner--dev--1.0--patch-169 * planner.el: Okay, modifying tasks without leaving the extra buffers open should work better now. However, this functionality hits the hard disk a bit. If you find yourself bothered by it, you can set planner-tasks-file-behavior to nil so that no processing is done. (planner-mode): Use the -maybe versions of the automatic functions. (planner-save-buffers): New parameter SUPPRESS-FIXING turns off automatic planner munging. This prevents jumping cursors. (planner-sort-tasks-maybe): New. (planner-renumber-tasks-maybe): New. (planner-renumber-notes-maybe): New. (planner-align-tasks-maybe): New. (planner-replan-task): Suppress fixing. (planner-copy-or-move-task): Suppress fixing. (planner-update-task): Suppress fixing. (planner-delete-task): Honor planner-tasks-file-behavior. (planner-create-task-from-info): Honor planner-tasks-file-behavior. (planner-replan-task): Hide planner-tasks-file-behavior from inner function. modified files: planner.el 2004-09-24 03:45:37 GMT Sacha Chua patch-168 Summary: Docfix: Mention _emacs for Microsoft Windows Revision: planner--dev--1.0--patch-168 * planner.texi: Mention _emacs for Microsoft Windows. Thanks to Miguel Marcos for the suggestion. modified files: planner.texi 2004-09-21 11:07:56 GMT Sacha Chua patch-167 Summary: Bugfix: planner-update-task: Actually follow planner-tasks-file-behavior Revision: planner--dev--1.0--patch-167 modified files: planner.el 2004-09-21 10:14:35 GMT Sacha Chua patch-165 Summary: planner-replan-task: minor bugfix Revision: planner--dev--1.0--patch-165 * planner.el (planner-replan-task): Correct small bug: buffer-list should be live-buffers variable. (That should teach me to make sure planner.el byte-compiles cleanly before checking it in...) modified files: planner.el 2004-09-21 10:13:03 GMT Sacha Chua patch-164 Summary: NOTE: planner-tasks-file-behavior option. Closes opened files by default. Revision: planner--dev--1.0--patch-164 * planner.el (planner-update-task), (planner-copy-or-move-task), (planner-copy-or-move-region), (plan): Obey planner-tasks-file-behavior (planner-tasks-file-behavior): New customizable option controls the behavior of task creation and updates. If set to 'close (default), newly-opened files are saved and closed. See variable documentation for more details. (planner-save-buffers): Add BUFFER-LIST parameter to allow restoring to a particular buffer list. * planner.texi (Variables to Customize): Document planner-tasks-file-behavior. modified files: planner.el planner.texi 2004-09-19 06:36:59 GMT Michael Olson patch-5 Summary: Fix scenario where the old project name still existed in project list after being changed. Revision: planner--mwolson--1.0--patch-5 2004-09-19 Michael Olson * planner.el (planner-project-default-name): New variable that indicates what the default value of `planner-project' will be set to. (planner-project): Use `planner-project-default-name' for default value instead of a string. (planner-update-wiki-project): Add comments and remove any items from `emacs-wiki-projects' that are associated with the default name found in `planner-project-default-name'. modified files: planner.el 2004-09-16 19:26:04 GMT Michael Olson patch-3 Summary: Replace `.' with `\\.' in some regexps to be more correct Revision: planner--mwolson--1.0--patch-3 2004-09-16 Michael Olson * planner.el (planner-create-note): Change use of `.' in regexp to `\\.'. (planner-highlight-notes): Ditto. modified files: planner.el 2004-09-16 10:53:28 GMT Sacha Chua patch-163 Summary: Merge patch for planner-create-note whitespacing Revision: planner--dev--1.0--patch-163 * planner.el: Merge 2004-09-12 patch from Michael Olson (mwolson AT member.fsf.org). His changelog follows. (planner-project): Make this variable customizable so that people are not stuck with "WikiPlanner" as the project name. (planner-seek-task-creation-point): Use (bolp) instead of a much-longer method to determine whether the point is at the beginning of the line. (planner-create-note): Ditto. Only insert newlines if we are not at the end of the buffer. modified files: planner.el 2004-09-16 10:10:56 GMT Sacha Chua patch-162 Summary: planner-diary: Separate multiple days with horizontal rules Revision: planner--dev--1.0--patch-162 * planner-diary.el (planner-diary-get-diary-entries): Feature: deal with multiple days properly. Replace ==== inserted by fancy-diary-display with ----, which will be replaced by a horizontal line. Thanks to Michael Olson for pointing this out. modified files: planner-diary.el 2004-09-16 03:13:07 GMT Michael Olson patch-2 Summary: Make project name customizable, fix spurious newlines in notes Revision: planner--mwolson--1.0--patch-2 2004-09-12 Michael Olson * planner.el (planner-project): Make this variable customizable so that people are not stuck with "WikiPlanner" as the project name. (planner-seek-task-creation-point): Use (bolp) instead of a much-longer method to determine whether the point is at the beginning of the line. (planner-create-note): Ditto. Only insert newlines if we are not at the end of the buffer. modified files: planner.el 2004-08-28 06:48:26 GMT Sacha Chua patch-161 Summary: New: planner-unix-mail Revision: planner--dev--1.0--patch-161 * planner-unix-mail.el: New from Frederik Fouvry. * planner.texi (Top): Document planner-unix-mail. new files: .arch-ids/planner-unix-mail.el.id planner-unix-mail.el modified files: planner.texi 2004-08-16 08:24:25 GMT Sacha Chua patch-160 Summary: New: planner-use-task-numbers Revision: planner--dev--1.0--patch-160 * planner.el (planner-use-task-numbers): New option. (planner-format-task): Obey planner-use-task-numbers. (planner-highlight-tasks): Allow unnumbered tasks. (planner-create-task): Bugfix: nil plan pages. * planner.texi (Task Numbering): Document planner-use-task-numbers. modified files: planner.el planner.texi 2004-08-16 07:32:52 GMT Sacha Chua patch-159 Summary: Move planner-diary options to separate customization group Revision: planner--dev--1.0--patch-159 * planner-diary.el (planner-diary): New customization group. Move all planner-diary options under it. modified files: planner-diary.el 2004-08-16 07:29:28 GMT Sacha Chua patch-158 Summary: Prefer local-write-file-hooks over write-file-hooks Revision: planner--dev--1.0--patch-158 * planner-id.el (planner-id-setup): Prefer local-write-file-hooks over write-file-hooks. Thanks to Frederik Fouvry for pointing this out. modified files: planner-id.el 2004-08-16 07:27:37 GMT Sacha Chua patch-157 Summary: New: planner-sort-undated-tasks-equivalent Revision: planner--dev--1.0--patch-157 * planner.el (planner-sort-tasks): Merge Maciej Kalisiak's patch to sort dated tasks before undated ones. Control via planner-sort-undated-tasks-equivalent. (planner-sort-undated-tasks-equivalent): New. * planner.texi (Making Files Pretty): Document planner-sort-undated-tasks-equivalent. modified files: planner.el planner.texi 2004-08-15 13:10:58 GMT Sacha Chua patch-156 Summary: New: planner-mhe.el Revision: planner--dev--1.0--patch-156 * planner-mhe.el: New. Contributed by Christophe Garion. * planner.texi (MH-E): New. new files: .arch-ids/planner-mhe.el.id planner-mhe.el modified files: planner.texi 2004-08-15 13:05:28 GMT Sacha Chua patch-155 Summary: Doc: Byte-compilation and info installation Revision: planner--dev--1.0--patch-155 * planner.texi (Advanced Installation): Merge John Sullivan and Raymond Zeitler's instructions for byte-compilation and info installation. modified files: planner.texi 2004-08-06 18:44:56 GMT Sacha Chua patch-154 Summary: Docfix: Dangling menus Revision: planner--dev--1.0--patch-154 modified files: planner.texi 2004-08-06 18:30:50 GMT Sacha Chua patch-153 Summary: planner.texi: major refactoring, split emacs-wiki and remember doc off Revision: planner--dev--1.0--patch-153 * planner.texi: Major refactoring. Move emacs-wiki and remember documentation to their own info files. Rearrange sections. modified files: planner.texi 2004-08-06 09:39:20 GMT Sacha Chua patch-152 Summary: Docfix for bug in patch-151: @end defopt Revision: planner--dev--1.0--patch-152 * planner.texi (Making Files Pretty): Docfix. modified files: planner.texi 2004-08-06 09:28:03 GMT Sacha Chua patch-151 Summary: Merge patch separating task sorting from renumbering Revision: planner--dev--1.0--patch-151 * planner.el: Merge patch from Maciej Kalisiak separating sorting from renumbering. (planner-sort-tasks-automatically): New. (planner-renumber-tasks-automatically): Control only renumbering. (planner-mode): Add planner-sort-tasks-automatically hook. (planner-sort-tasks): Move sorting code from planner-renumber-tasks. (planner-renumber-tasks): Remove sorting code, leaving renumbering code. (planner-fix-tasks): New. * planner.texi (Changing Tasks): Mention planner-fix-tasks. (Making Files Pretty): Fix typo. Document planner-renumber/sort/align-tasks-automatically. (List of Interactive Functions): Document planner-renumber/sort/align/fix-tasks. modified files: planner.el planner.texi 2004-08-06 07:28:57 GMT Sacha Chua patch-150 Summary: Accept functions for planner-day/plan-page-template Revision: planner--dev--1.0--patch-150 * planner.el (planner-day-page-template): Accept a function. (planner-plan-page-template): Accept a function. (planner-page-default-p): Add note about planner-day-page-template. Make sure it only checks string templates. (planner-prepare-file): Allow the use of functions. * planner.texi (Customizing Your Day Pages): Update note about planner-day-page-template. modified files: planner.el planner.texi 2004-08-06 06:41:45 GMT Sacha Chua patch-149 Summary: New: planner-edit-task-description Revision: planner--dev--1.0--patch-149 * planner.el (planner-edit-task-description): New. Thanks to Daniel Martins for the feature suggestion. * planner.texi (Changing Tasks): Add note about planner-edit-task-description. (List of Interactive Functions): Describe planner-edit-task-description. modified files: planner.el planner.texi 2004-08-06 06:10:02 GMT Sacha Chua patch-148 Summary: planner-raise-task: Automatically reorder priorities on the linked page Revision: planner--dev--1.0--patch-148 * planner.el (planner-raise-task): Automatically reorder priorities on linked pages. Thanks to Hans Halvorson for the suggestion. modified files: planner.el 2004-08-02 14:37:39 GMT Sacha Chua patch-147 Summary: Bugfix: planner-vm-browse-url: Properly open message Revision: planner--dev--1.0--patch-147 * planner-vm.el (planner-vm-browse-url): Merge patch from Jürgen Doser. modified files: planner-vm.el 2004-07-28 09:04:50 GMT Sacha Chua patch-146 Summary: Bugfix: Make task pages links when tasks are created Revision: planner--dev--1.0--patch-146 * planner.el (planner-create-task): Bugfix: Make task pages links. modified files: planner.el 2004-07-28 09:01:42 GMT Sacha Chua patch-145 Summary: New: planner-raise-task-category, planner-lower-task-category Revision: planner--dev--1.0--patch-145 * planner.el (planner-menu): Change menu to use task categories instead. * planner.texi (List of Interactive Functions): Document planner-raise-task-category, planner-lower-task-category. * planner.el (planner-raise-task-category): New. (planner-lower-task-category): New. modified files: planner.el planner.texi 2004-07-24 13:02:54 GMT Sacha Chua patch-144 Summary: Show planner-annotation-from-planner-note number Revision: planner--dev--1.0--patch-144 * planner.el (planner-annotation-from-planner-note): Show the note number in the link so that people know it refers to a note. Thanks to Paul Lussier for the feature request. modified files: planner.el 2004-07-24 12:57:50 GMT Sacha Chua patch-143 Summary: Bugfix: Understand tasks with parenthesized non-link text Revision: planner--dev--1.0--patch-143 * planner.el: Be more understanding of tasks that include parenthesized non-link text. Thanks to John Anderson for pointing this out. (planner-task-info-from-string): Make sure the link text is really a link before setting planner-task-link. (planner-format-task): Do not unconditionally make links. * planner-id.el (planner-id-add-task-id): Check if there's a linked task. (planner-id-jump-to-linked-task): Use planner-find-file instead of emacs-wiki-find-file. modified files: planner-id.el planner.el 2004-07-24 12:29:48 GMT Sacha Chua patch-142 Summary: Bugfix: Improve overlay handling Revision: planner--dev--1.0--patch-142 * planner.el: Depends on emacs-wiki--dev--1.0--patch-53. (planner-zap-overlays): New. (planner-mode): Don't forget to zap overlays before highlighting tasks and notes. (planner-highlight-tasks): Honor END. (planner-highlight-region): Tag it with 'planner t. modified files: planner.el 2004-07-23 01:55:49 GMT Sacha Chua patch-141 Summary: Bugfix: planner-read-date: Remove use of kbd Revision: planner--dev--1.0--patch-141 * planner.el (planner-read-date): Remove use of kbd, as it doesn't seem to be available under XEmacs/FreeBSD with the current requires. Thanks to George Hartzell for the bug report. modified files: planner.el 2004-07-15 06:57:50 GMT Sacha Chua patch-140 Summary: planner-seek-next-unfinished-task Revision: planner--dev--1.0--patch-140 * planner.el (planner-seek-next-unfinished-task): New. * planner.texi (Viewing Tasks): Add note about planner-seek-next-unfinished-task. modified files: planner.el planner.texi 2004-07-15 06:39:01 GMT Sacha Chua patch-139 Summary: Add note about hierarchical tasks to planner.texi Revision: planner--dev--1.0--patch-139 * planner.texi (Hierarchical Tasks): New note. modified files: planner.texi 2004-07-13 12:27:58 GMT Sacha Chua patch-138 Summary: Bugfix: Refresh file alist after saving buffers in plan Revision: planner--dev--1.0--patch-138 * planner.el (plan): Refresh file alist after saving buffers. modified files: planner.el 2004-07-13 08:38:03 GMT Sacha Chua patch-137 Summary: Add planner-ledger.el Revision: planner--dev--1.0--patch-137 * planner-ledger.el: New from Will Glozer. Modifications: Pass checkdoc. (planner-ledger-payment-task-regexp): Make regular expression more flexible (not just USD). * planner.texi (Using planner-ledger.el): New. new files: .arch-ids/planner-ledger.el.id planner-ledger.el modified files: planner.texi 2004-06-29 06:57:33 GMT Sacha Chua patch-136 Summary: Docfix: remember-planner-append-hook Revision: planner--dev--1.0--patch-136 * planner-rss.el: Update note about remember-planner-append-hook. Thanks to Michael Olson for the patch. * planner.texi (Using planner-rss.el): Update note about remember-planner-append-hook. Thanks to Michael Olson for the patch. modified files: planner-rss.el planner.texi 2004-06-28 04:43:01 GMT Sacha Chua patch-135 Summary: Menu tweaks: planner notes submenu, new keybindings Revision: planner--dev--1.0--patch-135 * planner.el: Merge patch from Michael Olson. (planner-install-extra-note-keybindings): Add a new function `planner-install-extra-note-keybindings', modeled after `planner-install-extra-task-keybindings', that makes all of the note-related entries in the Planner menu keyboard-accessible. The prefix for all of these keys is C-c C-o, since C-c C-n was already in use. (planner-menu): Add a submenu called "Notes" to the Planner menu. (planner-menu): Fix the "Info" menu entry so that it brings up the planner info manual instead of displaying a message. This item is now called "Info manual". (planner-menu): Change the Goto submenu so that the word "Goto" is removed from the beginning of each entry. It seems ambiguous to have it there. modified files: planner.el 2004-06-26 09:00:00 GMT Sacha Chua patch-134 Summary: Document different ways to plan (bare-bones) Revision: planner--dev--1.0--patch-134 * planner.texi (Bare-Bones Planning): New. (Bare-Bones Planning with Plan Pages): New. (Tasks on Plan Pages with Some Day Pages): New. (Planning based on the Franklin-Covey Approach): Renamed. modified files: planner.texi 2004-06-26 08:21:59 GMT Sacha Chua patch-133 Summary: Bugfix: Change defvars to defcustoms Revision: planner--dev--1.0--patch-133 modified files: planner.el 2004-06-26 08:05:03 GMT Sacha Chua patch-132 Summary: Make note/task renumbering optional Revision: planner--dev--1.0--patch-132 * planner.el (planner-renumber-notes-automatically): New. (planner-renumber-tasks-automatically): New. (planner-align-tasks-automatically): New. * planner.texi (Making Files Pretty): Document new options. * planner.el (planner-mode): Do not automatically align and renumber tasks and notes. modified files: planner.el planner.texi 2004-06-26 07:47:53 GMT Sacha Chua patch-131 Summary: planner-gnus: Add check for from, copy article buffer Revision: planner--dev--1.0--patch-131 * planner-gnus.el (planner-gnus-annotation-from-summary): Add check for from. (planner-gnus-annotation-from-message): Copy the article buffer. Add check for from. modified files: planner-gnus.el 2004-06-26 07:43:54 GMT Sacha Chua patch-130 Summary: Bugfix: Make sure user-mail-address is not the blank string Revision: planner--dev--1.0--patch-130 * planner.el (planner-ignored-from-addresses): Make sure user-mail-address is not the blank string. modified files: planner.el 2004-06-26 07:34:08 GMT Sacha Chua patch-129 Summary: New option: planner-use-day-pages allows you to turn off dates for tasks and notes Revision: planner--dev--1.0--patch-129 * planner.el (planner-use-day-pages): New option allows you to turn off the use of day pages for tasks and notes. If not using day pages, WecomePage is the default page. (planner-name-regexp): If not using day pages, use blank regexp. (planner-mode-map): If not using day pages, do not bind day navigation. (planner-menu): If not using day pages, do not add day navigation to menus. (planner-read-date): Don't read anything if not using day pages. (planner-goto): Read plan page if date page not specified. (planner-goto-most-recent): Do not call plan automatically. (planner-today): Return WelcomePage if not using day pages. (planner-update-wiki-project): Do not add empty regexp. modified files: planner.el planner.texi 2004-06-26 06:23:24 GMT Sacha Chua patch-128 Summary: New: planner-note-headline-face Revision: planner--dev--1.0--patch-128 * planner.el (planner-note-headline-face): Make customizable face. (planner-highlight-notes): Use headline face. Thanks to people on #emacs for the feedback. modified files: planner.el 2004-06-26 05:06:45 GMT Sacha Chua patch-127 Summary: planner-authz.el update from ajk Revision: planner--dev--1.0--patch-127 * planner-authz.el: Merge update from ajk removing cl dependency. 2004-06-25 16:10:11 GMT Sacha Chua patch-126 Summary: Remove stray paren Revision: planner--dev--1.0--patch-126 * planner.el (planner-create-task-from-buffer): Remove stray paren. Embarrassing! modified files: planner.el 2004-06-25 15:26:49 GMT Sacha Chua patch-125 Summary: planner-gnus: Use gnus-article-buffer if available Revision: planner--dev--1.0--patch-125 * planner-gnus.el (planner-gnus-get-message-id): Save excursion and use current buffer. (planner-gnus-annotation-from-summary): Use planner-make-link. (planner-gnus-annotation-from-message): Test against gnus-article-mode and gnus-original-article-mode. Use the gnus-article-buffer if available. modified files: planner-gnus.el 2004-06-25 15:26:07 GMT Sacha Chua patch-124 Summary: planner.el task creation bugfixes: annotations, plan pages Revision: planner--dev--1.0--patch-124 * planner.el (planner-create-task): Bugfix: Tweak annotation rules so that annotation does not preempt plan page. Do not use plan page unless specified. (planner-create-task-from-buffer): Use planner- functions instead of emacs-wiki- functions. Bugfix: Do not use plan page unless specified. modified files: planner.el 2004-06-25 14:29:45 GMT Sacha Chua patch-123 Summary: Make planner-mode-hook customizable Revision: planner--dev--1.0--patch-123 * planner.el (planner-mode-hook): Make planner-mode-hook customizable. Thanks to bigmike160 for pointing this out. * planner.texi (Variables to Customize): Add planner-mode-hook. modified files: planner.el planner.texi 2004-06-25 13:44:32 GMT Sacha Chua patch-122 Summary: Embarrassing bugfix: Remove stray ) Revision: planner--dev--1.0--patch-122 * planner-gnus.el (planner-gnus-annotation-from-message): Remove stray ) modified files: planner-gnus.el 2004-06-25 13:43:21 GMT Sacha Chua patch-121 Summary: Important bugfix: planner-gnus.el and annotations from articles Revision: planner--dev--1.0--patch-121 * planner-gnus.el (planner-gnus-get-message-id): Important bugfix: Revert to if. (planner-gnus-get-address): Important bugfix: Use original article buffer. (planner-gnus-annotation-from-message): Important bugfix: Use original article buffer. modified files: planner-gnus.el 2004-06-25 13:34:11 GMT Sacha Chua patch-120 Summary: planner-gnus: Add major-mode check to annotations from messages Revision: planner--dev--1.0--patch-120 * planner-gnus.el (planner-gnus-get-address): Use the current buffer, whatever it is. (planner-gnus-get-message-id): Change if to when. (minor) (planner-gnus-annotation-from-message): Add major-mode check. Thanks to Rainer Volz for the bug report. modified files: planner-gnus.el 2004-06-25 05:14:28 GMT Sacha Chua patch-119 Summary: Update planner-authz.el to ajk's 1.20 Revision: planner--dev--1.0--patch-119 * planner-authz.el: Update to ajk's 1.20. modified files: planner-authz.el 2004-06-24 14:55:16 GMT Sacha Chua patch-118 Summary: Move planner-accomplishments and planner-tasks-overview documentation to "Using PlannerMode" Revision: planner--dev--1.0--patch-118 * planner.texi (Using planner-accomplishments.el): Move to "Using Planner" section. Add example. (Using planner-tasks-overview.el): Add a small example. modified files: planner.texi 2004-06-24 04:55:09 GMT Sacha Chua patch-117 Summary: planner-annotation-strip-directory: new customizable option Revision: planner--dev--1.0--patch-117 * planner.el (planner-annotation-from-file): Use planner-annotation-strip-directory. Thanks to Hoan Ton-That for the idea and base patch. (planner-annotation-strip-directory): Make customizable. (planner-annotation-use-relative-file): Make customizable. * planner.texi (Introducing Annotation Functions): Document planner-annotation-functions, planner-annotation-strip-directory, planner-annotation-use-relative-file. modified files: planner.el planner.texi 2004-06-24 04:34:49 GMT Sacha Chua patch-116 Summary: Merge tweaked patch from ajk changing use of planner-name-regexp to planner-date-regexp in planner-authz.el Revision: planner--dev--1.0--patch-116 * planner-authz.el: Merge tweaked patch from ajk changing use of planner-name-regexp to planner-date-regexp. (planner-authz-day-p): Use planner-date-regexp instead of planner-name-regexp. Accept an optional parameter PAGE. (planner-authz-default): Use planner-authz-day-p instead of duplicating the test. (planner-authz-users): Docfix: Use planner-date-regexp instead of planner-name-regexp. modified files: planner-authz.el 2004-06-23 16:55:57 GMT Sacha Chua patch-115 Summary: Add planner-rss size/item limits Revision: planner--dev--1.0--patch-115 * planner-rss.el (planner-rss-feed-limits): New user option. (planner-rss-add-item): Use planner-rss-limit. (planner-rss-limit): New. (planner-rss-limit-size): New. (planner-rss-limit-items): New. * planner.texi (Using planner-rss.el): Document planner-rss feed limit option. modified files: planner-rss.el planner.texi 2004-06-23 06:50:40 GMT Sacha Chua patch-114 Summary: planner.texi update from johnsu01 Revision: planner--dev--1.0--patch-114 * planner.texi: Merge update from johnsu01. Task description much clearer. modified files: planner.texi 2004-06-22 13:29:26 GMT Sacha Chua patch-113 Summary: NEW: planner-authz.el Revision: planner--dev--1.0--patch-113 * planner-authz.el: New module contributed by Andrew J. Korty. Modified to pass checkdoc. * planner.texi (Using planner-authz.el): New. (Components): Add entry for planner-authz.el new files: .arch-ids/planner-authz.el.id planner-authz.el modified files: planner.texi 2004-06-22 13:27:41 GMT Sacha Chua patch-112 Summary: planner-read-date: take optional arg `prompt' Revision: planner--dev--1.0--patch-112 * planner.el (planner-read-date): Add optional prompt argument. modified files: planner.el 2004-06-20 10:53:04 GMT Sacha Chua patch-111 Summary: Update planner.texi from johnsu01 Revision: planner--dev--1.0--patch-111 modified files: planner.texi 2004-06-19 16:25:57 GMT Sacha Chua patch-110 Summary: Remove duplicate defcustom for planner-template-fuzz-factor Revision: planner--dev--1.0--patch-110 * planner.el (planner-template-fuzz-factor): Remove duplicate defcustom. Thanks to johnsu01 for pointing this out. modified files: planner.el 2004-06-18 16:55:30 GMT Sacha Chua patch-109 Summary: planner-bbdb: Add mailto: URLs to e-mail addresses Revision: planner--dev--1.0--patch-109 * planner-bbdb.el (planner-bbdb-resolve-url): Add the mailto: URL. Thanks to ajk for bug report and patch idea modified files: planner-bbdb.el 2004-06-15 03:19:29 GMT Sacha Chua patch-108 Summary: Docfix: Change mention of rmail to vm in planner-vm.el Revision: planner--dev--1.0--patch-108 * planner-vm.el: Docfix: Change mention of rmail to vm. modified files: planner-vm.el 2004-06-15 03:17:59 GMT Sacha Chua patch-107 Summary: Tweak: Move planner-rss options to planner-rss group Revision: planner--dev--1.0--patch-107 * planner-rss.el (planner-rss): New. (planner-rss-base-url): Move to planner-rss group. (planner-rss-category-feeds): Move to planner-rss group. modified files: planner-rss.el 2004-06-12 13:55:23 GMT Sacha Chua patch-106 Summary: NOTE: Prefix argument now means associate task with current plan/date page, if any Revision: planner--dev--1.0--patch-106 * planner.el (planner-create-task-from-buffer): NOTE: Change behavior of prefix argument. Prefix now means associate the task with the current planner page, if any. (planner-create-task): Follow usage of planner-create-task-from-buffer. Thanks to Yvonne Thomson for the suggestions. * planner.texi (List of Interactive Functions): Update descriptions of planner-create-task-from-buffer and planner-create-task. modified files: planner.el planner.texi 2004-06-12 13:39:23 GMT Sacha Chua patch-105 Summary: NOTE: planner-create-task prompts for plan page unless prefix argument is supplied Revision: planner--dev--1.0--patch-105 * planner.el (planner-create-task): Add prefix argument which controls whether or not to prompt for a plan page. Thanks to Yvonne Thomson for the suggestion. * planner.texi (List of Interactive Functions): Update documentation for planner-create-task to include prefix arg. modified files: planner.el planner.texi 2004-06-11 15:43:31 GMT Sacha Chua patch-104 Summary: Important bugfix: Add condition-case just in case calendar is not displayed Revision: planner--dev--1.0--patch-104 * planner.el (planner-create-task-from-buffer): Bugfix: Add condition-case just in case calendar is not displayed. modified files: planner.el 2004-06-11 14:16:57 GMT Sacha Chua patch-103 Summary: NOTE: planner-create-task-from-buffer in a calendar buffer will use the currently-selected date for the task Revision: planner--dev--1.0--patch-103 * planner.el (planner-create-task-from-buffer): Default date to date currently selected in calendar. Do not prompt if creating task based on that date. Thanks to Yvonne Thomson for the idea. modified files: planner.el 2004-06-11 14:02:17 GMT Sacha Chua patch-102 Summary: planner-id.el: Promote planner-id-update-automatically to a user-customizable variable Revision: planner--dev--1.0--patch-102 * planner-id.el (planner-id-update-automatically): Promote to defcustom. Thanks to Yvonne Thomson for the suggestion. (planner-id): New customize group. (planner-id-add-task-id-flag): Move to planner-id group. (planner-id-tracking-file): Move to planner-id group. (planner-id-face): Move to planner-id group. * planner.texi (Using planner-id.el): Update defvars to defopts. modified files: planner-id.el planner.texi 2004-06-08 12:37:53 GMT Sacha Chua patch-101 Summary: Bugfix: planner-tasks-overview.el keymap Revision: planner--dev--1.0--patch-101 * planner-tasks-overview.el (planner-tasks-overview): Correct typo in keymap. Thanks to ajk for the bug report and patch. modified files: planner-tasks-overview.el 2004-06-03 14:49:01 GMT Sacha Chua patch-100 Summary: Bugfix: Revert planner-task-cancelled keybinding Revision: planner--dev--1.0--patch-100 * planner.el (planner-install-extra-task-keybindings): Bugfix: Revert planner-task-cancelled keybinding for extra task keybindings. modified files: planner.el 2004-06-03 14:44:10 GMT Sacha Chua patch-99 Summary: Bugfix: Make C-S-x work under XEmacs Revision: planner--dev--1.0--patch-99 * planner.el (planner-mode-map): Make it work for XEmacs. (planner-install-extra-task-keybindings): Make it work for XEmacs. Thanks to pll for pointing this out. Apparently, I need to be careful about the shift modifier... modified files: planner.el 2004-06-03 11:46:44 GMT Sacha Chua patch-98 Summary: New feature: planner-tasks-overview Revision: planner--dev--1.0--patch-98 * planner-tasks-overview.el: New. * planner.texi: Document planner-tasks-overview.el. new files: .arch-ids/planner-tasks-overview.el.id planner-tasks-overview.el modified files: planner.texi 2004-06-02 08:01:16 GMT Sacha Chua patch-97 Summary: planner-calendar.el updates from Gary, and inclusion in doc Revision: planner--dev--1.0--patch-97 * planner.texi: Add documentation for planner-calendar.el. modified files: planner.texi 2004-06-01 22:11:01 GMT Sacha Chua patch-96 Summary: planner.texi: Document planner-accomplishments.el Revision: planner--dev--1.0--patch-96 * planner.texi: Add documentation for planner-accomplishments.el. modified files: planner.texi 2004-06-01 21:58:29 GMT Sacha Chua patch-95 Summary: planner-accomplishments.el: Display per-status totals Revision: planner--dev--1.0--patch-95 * planner-accomplishments.el (planner-accomplishments-format-table): Display per-status totals. modified files: planner-accomplishments.el 2004-06-01 21:51:08 GMT Sacha Chua patch-94 Summary: Feature: planner-accomplishments.el Revision: planner--dev--1.0--patch-94 * planner-accomplishments.el: New. new files: .arch-ids/planner-accomplishments.el.id planner-accomplishments.el 2004-06-01 11:35:08 GMT Gary V. Vaughan patch-3 Summary: new functions to enable today.html publishing Revision: planner--gary--1.0--patch-3 * planner-calendar.el (planner-calendar-today): New function to find the newest day page. (planner-calendar-create-today-link): New function to actually create a today.html link to the newest published day page. (planner-calendar-today-page-name): Customizable default day page base name. modified files: planner-calendar.el 2004-05-31 16:04:08 GMT Sacha Chua patch-93 Summary: Docfix: planner task keybindings Revision: planner--dev--1.0--patch-93 * planner.el (planner-install-extra-context-keybindings): Add note about added keybindings. Thanks to forcer. (planner-install-extra-task-keybindings): Added note about function definition. Still haven't figured out how to manage keymaps gracefully. (planner-search-notes): Satisfy checkdoc. * planner.texi (Navigation): Update documentation for planner-goto-yesterday. Thanks to forcer for pointing this out. modified files: planner.el planner.texi 2004-05-26 14:30:56 GMT Sacha Chua patch-92 Summary: Bugfix: planner-diary-get-diary-entries should return "No entries" Revision: planner--dev--1.0--patch-92 * planner-diary.el (planner-diary-get-diary-entries): Return "No entries" if diary returns no entries. Returning an empty string screws up lisp tags. modified files: planner-diary.el 2004-05-26 06:53:01 GMT Sacha Chua patch-91 Summary: Bugfix: Pass correct arguments in planner-diary-entries-here Revision: planner--dev--1.0--patch-91 * planner-diary.el (planner-diary-entries-here): Bugfix: Pass correct arguments to planner-diary-get-diary-entries. It should be DATE DAYS FILE, not DATE FILE DAYS. Thanks to Brett Presnell for the bug report. modified files: planner-diary.el 2004-05-25 07:22:35 GMT Sacha Chua patch-90 Summary: Bugfix: typo, boolean should be a symbol Revision: planner--dev--1.0--patch-90 * planner.el (planner-hide-task-status-when-highlighting): Bugfix: typo, 'boolean should be a symbol. modified files: planner.el 2004-05-25 07:21:45 GMT Sacha Chua patch-89 Summary: Bugfix: Do not insert file contents literally, as this screws up encoding Revision: planner--dev--1.0--patch-89 * planner.el (planner-extract-tasks): Do not insert file contents literally. (planner-search-notes-internal): Do not insert file contents literally. (planner-past-notes-tag): Do not insert file contents literally. modified files: planner.el 2004-05-25 07:19:21 GMT Sacha Chua patch-88 Summary: planner-export-diary: Simplify code, do not use insert-contents-literally Revision: planner--dev--1.0--patch-88 * planner-export-diary.el (planner-export-diary-future): Use planner-export-diary. (planner-export-diary-get-schedule-entries): Do not insert contents literally. Allow spaces at the start of appointment lines. Construct the list using cons instead of append. Note: This function does not guarantee any particular order. Thanks to Xin Wei Hu for bug report and patch for both changes. modified files: planner-export-diary.el 2004-05-25 07:10:27 GMT Sacha Chua patch-87 Summary: Rearrange user customizations, promote some defvars to defcustoms Revision: planner--dev--1.0--patch-87 * planner.el (planner-tasks): New customize group. (planner-carry-tasks-forward): Move to planner-tasks group. (planner-marks-regexp): Move to planner-tasks group. (planner-default-task-priority): Move to planner-tasks group. (planner-add-task-at-end-flag): Move to planner-tasks group. Promote from defvar. (planner-emacs-wiki): New customize group. (planner-name-regexp): Move to planner-emacs-wiki group. (planner-custom-variables): Move to planner-emacs-wiki group. (planner-publishing-markup): Move to planner-emacs-wiki group. (planner-markup-tags): Move to planner-emacs-wiki group. (planner-fontlock): New customize group. (planner-completed-task-face): Move to planner-fontlock group. (planner-cancelled-task-face): Move to planner-fontlock group. (planner-delegated-task-face): Move to planner-fontlock group. (planner-in-progress-task-face): Move to planner-fontlock group. (planner-high-priority-task-face): Move to planner-fontlock group. (planner-medium-priority-task-face): Move to planner-fontlock group. (planner-low-priority-task-face): Move to planner-fontlock group. (planner-default-page): Promote to user option under planner-tasks. (planner-hide-task-status-when-highlighting): Promote to user option under planner-fontlock. (planner-create-task-hook): Promote to user option under planner-tasks. (planner-task-dates-favor-future-p): Promote to user option under planner-tasks. (planner-expand-name-favor-future-p): Promote to user option under planner. modified files: planner.el planner.texi 2004-05-20 21:03:55 GMT Gerd Flaig patch-1 Summary: fixed docstring Revision: planner--dev--1.0--patch-1 The docstring for planner-lisp-browse-url was wring. Fixed it. modified files: planner-lisp.el 2004-05-20 12:07:52 GMT Gary V. Vaughan patch-2 Summary: render calendar day links correctly Revision: planner--gary--1.0--patch-2 * planner-calendar.el (planner-calendar): Correct an arithmetic error that made calender day page links point from the wrong cell. modified files: planner-calendar.el 2004-05-20 07:32:29 GMT Sacha Chua patch-85 Summary: Bugfix: Set reasonable defaults for planner-rss.el Revision: planner--dev--1.0--patch-85 * planner-rss.el (planner-rss-base-url): Default to "". (planner-rss-category-feeds): Default to nil. (planner-rss-file-name): Add note about file name. Thanks to Jan Alonzo for pointing this out. modified files: planner-rss.el 2004-05-19 03:40:33 GMT Sacha Chua patch-84 Summary: planner-export-diary: Bugfix: Use planner-export-diary-file Revision: planner--dev--1.0--patch-84 * planner-export-diary.el (planner-export-diary): Use planner-export-diary-file. (planner-export-diary-future): Use planner-export-diary-file. modified files: planner-export-diary.el 2004-05-14 06:17:51 GMT Sacha Chua patch-83 Summary: planner-rss.el: NOTE: accept functions for conditions and phase out planner-rss-filename, planner-rss-initial-contents Revision: planner--dev--1.0--patch-83 * planner-rss.el (planner-rss-initial-contents): NOTE: Move default value into planner-rss-category-feeds. Demote from customizable user option to global variable. (planner-rss-file-name): NOTE: Move into planner-rss-category-feeds. Demote from customizable user option to global variable. (planner-rss-category-feeds): Add default entry for all blog items. Allow choice between regular expression and function. (planner-rss-initialize): Remove. Move code into planner-rss-add-item. (planner-rss-add-item): Initialize file if necessary. (planner-rss-add-note): New argument FEED allows you to specify feed. New code for allowing the first element of planner-rss-category-feeds elements to be a function. Ensure that blog entries are not duplicated. * planner.texi (Using planner-rss.el): Add usage note for planner-rss-category-feeds. modified files: planner-rss.el planner.texi 2004-05-13 05:08:29 GMT Sacha Chua patch-82 Summary: Bugfix: Strip spaces for better recognition of planner-cyclic tasks Revision: planner--dev--1.0--patch-82 * planner-cyclic.el (planner-cyclic-get-cyclic-tasks): Strip spaces and recognize only task-like entries. Thanks to johnsu01 for pointing this bug out. modified files: planner-cyclic.el 2004-05-11 03:50:52 GMT Sacha Chua patch-81 Summary: NOTE: planner-id-add-task-id-flag Revision: planner--dev--1.0--patch-81 * planner.texi: Add category entry. (Components): Correct typo. (Using planner-id.el): Mention `planner-id-add-task-id-flag' and `planner-id-update-automatically'. * planner-id.el (planner-create-task-hook): Use `planner-id-add-task-id-maybe'. (planner-id-add-task-id-maybe): New. modified files: planner-id.el planner.texi 2004-05-11 03:44:40 GMT Sacha Chua patch-80 Summary: Alias planner-encode-url to emacs-wiki-escape-url Revision: planner--dev--1.0--patch-80 * planner.el (planner-encode-url): Alias of emacs-wiki-escape-url. Thanks to Frederik Fouvry for pointing this out. modified files: planner.el 2004-05-10 07:22:38 GMT Sacha Chua patch-79 Summary: planner.texi: Mention planner-create-task-{high,medium,low}-priority and planner-default-task-priority Revision: planner--dev--1.0--patch-79 * planner.texi (Creating a Task): Mention planner-create-task-{high,medium,low}-priority and planner-default-task-priority. * planner.texi: Change @var to @code where appropriate. modified files: planner.texi 2004-05-10 06:58:58 GMT Sacha Chua patch-78 Summary: planner.texi: planner-jump-to-linked-note Revision: planner--dev--1.0--patch-78 * planner.texi (Working With Notes): planner-jump-to-linked-note. modified files: planner.texi 2004-05-10 06:51:43 GMT Sacha Chua patch-77 Summary: planner.texi: planner-add-task-at-end-flag Revision: planner--dev--1.0--patch-77 * planner.texi (Variables to Customize): planner-add-task-at-end-flag . (List of Interactive Functions): Add note about planner-add-task-at-end-flag. modified files: planner.texi 2004-05-10 06:43:04 GMT Sacha Chua patch-76 Summary: Update planner.texi for planner-task-cancelled keybindings Revision: planner--dev--1.0--patch-76 * planner.texi (Ideas for Other Keybindings): Update extra task keybindings. (Changing Tasks): Change the notation for shifted keys. modified files: planner.texi 2004-05-10 06:24:23 GMT Sacha Chua patch-75 Summary: planner-timeclock: Clock in with planner-task-in-progress Revision: planner--dev--1.0--patch-75 * planner.texi (Using planner-timeclock.el): Add note about clocking in with `planner-task-in-progress' and clocking out with `timeclock-out' or `planner-task-done'. * planner-timeclock.el (planner-timeclock-in): Change to an alias of `planner-task-in-progress'. (planner-task-in-progress): New. Clock in on the current task, or change to it if already clocked in. (planner-task-done): Clock out only if clocked in. modified files: planner-timeclock.el planner.texi 2004-05-10 05:37:31 GMT Sacha Chua patch-74 Summary: Add planner-save-buffers to planner.texi Revision: planner--dev--1.0--patch-74 * planner.texi (List of Interactive Functions): Mention planner-save-buffers. modified files: planner.texi 2004-05-05 05:21:20 GMT John Sullivan patch-5 Summary: Documentation changes. Revision: planner-dev--john--1.0--patch-5 Small changes to remember-bbdb descriptions. Added defuns to planner.el list. Modified Working More With Tasks and Working More With Notes modified files: planner.texi 2004-05-04 17:23:37 GMT Sacha Chua patch-73 Summary: planner-highlight-tasks: Better XEmacs compatibility Revision: planner--dev--1.0--patch-73 * planner.el (planner-highlight-region): Better XEmacs compatibility. Should mark up completed tasks properly now. Thanks to hynek for pointing it out. (planner-highlight-tasks): Better XEmacs compatibility. modified files: planner.el 2004-05-04 16:29:18 GMT Sacha Chua patch-72 Summary: planner.texi: Getting started section: tasks fleshed out Revision: planner--dev--1.0--patch-72 * planner.texi: Patch is very ugly, sorry. Must break documentation changes down even smaller, but got carried away. (Top): Sentence-case descriptions, some changes. (Preface): Remove apology. (Introduction): Move description here instead of Preface. Collapse history. (Getting Started): Major rewrite. (Thoughts): New. Move essays under here, near the end. modified files: planner.texi 2004-05-04 14:29:29 GMT Sacha Chua patch-71 Summary: NOTE: Changed behavior of planner-carry-tasks-forward, now default for FORCE-DAYS (with minor tweaks) Revision: planner--dev--1.0--patch-71 * planner.el (planner-carry-tasks-forward): NOTE: Now behaves similar to the FORCE-DAYS parameter of `plan'. Defaults to scanning the past three days _AND_ carrying the tasks forward, as this makes more sense for new users. Always checks for new tasks. (plan): Follow new meaning of planner-carry-tasks-forward as the default. modified files: planner.el 2004-05-04 13:27:54 GMT Sacha Chua patch-70 Summary: Bugfix: Actually pass filename to function specified in planner-annotation-use-relative-file Revision: planner--dev--1.0--patch-70 * planner.el (planner-annotation-from-file): Actually pass file name, as promised. modified files: planner.el 2004-05-04 12:03:02 GMT Sacha Chua patch-69 Summary: planner.texi: Revise installation instructions Revision: planner--dev--1.0--patch-69 * planner.texi: Revise installation instructions. modified files: planner.texi 2004-05-04 09:29:11 GMT Sacha Chua patch-68 Summary: Use emacs-wiki-url-protocols code in emacs-wiki--dev--1.0--patch-26 Revision: planner--dev--1.0--patch-68 * planner.el (planner-custom-variables): No longer use emacs-wiki-browse-url-function. (planner-url-list, planner-url-regexp): NOTE: Use emacs-wiki-url-protocols instead. (planner-publishing-markup): Remove planner-markup-url. (planner-update-wiki-project): Remove planner-url-regexp. (planner-browse-url-*): Remove. (planner-add-protocol): New. * planner-wl.el: Add wl to protocols. (planner-wl-annotation-from-wl, planner-wl-browse-url): Autoload. * planner-vm.el: Add vm to protocols. (planner-vm-annotation-from-mail, planner-vm-browse-url): Autoload. * planner-rmail.el: Add rmail to protocols. (planner-rmail-annotation-from-mail, planner-rmail-browse-url): Autoload. * planner-lisp.el: Add lisp to protocols. (planner-lisp-browse-url): Autoload. * planner-gnus.el: Add gnus to protocols. (planner-gnus-insinuate, planner-gnus-annotation, planner-gnus-browse-url): Autoload. * planner-erc.el: Add erc and irc to protocols. (planner-erc-annotation-from-erc, planner-erc-browse-url): Autoload. * planner-bbdb.el: Add bbdb to protocols. (planner-bbdb-resolve-url, planner-bbdb-browse-url, planner-bbdb-annotation-from-bbdb): Autoload. modified files: planner-bbdb.el planner-erc.el planner-gnus.el planner-lisp.el planner-rmail.el planner-vm.el planner-wl.el planner.el 2004-05-03 03:26:32 GMT Sacha Chua patch-67 Summary: Bugfix: Misplaced paren in planner-create-task-from-info Revision: planner--dev--1.0--patch-67 * planner.el (planner-create-task-from-info): Bugfix: Misplaced paren. modified files: planner.el 2004-05-03 02:03:19 GMT Sacha Chua patch-66 Summary: Bugfix: planner-save-buffers problem with planner-id updates Revision: planner--dev--1.0--patch-66 * planner.el (planner-save-buffers): Try to fix problem with M-x plan rollover to new day by iterating over the buffer list instead of using save-buffers. Bug reported by Win Treese. modified files: planner.el 2004-05-03 00:51:06 GMT John Sullivan patch-1 Summary: Created branch to Sacha's planner-dev, revised planner.texi. Revision: planner-dev--john--1.0--patch-1 Added external refs for Emacs manual: Gnus, Calendar/Diary, Holidays, Appointments, Time Intervals. Fixed Rmail references. Minor cosmetic and typo fixes along the way. Added information about manually creating tasks without dates and/or project pages to "Working With Tasks". Added "Customizing Your Day Pages" section with @xref's to other sections. Added info about images to "Using emacs-wiki.el". Added info about listing unfinished tasks to "Working With Tasks". Added section "Introducing Annotation Functions" based on an email to emacs-wiki-discuss by Yvonne Thompson. Added info about the Gmane gateway for the mailing list, and the Orkut community to the "Getting Help" section. modified files: planner.texi 2004-04-30 09:15:11 GMT Sacha Chua patch-64 Summary: Bugfix: Allow multiple digits in +days or -days specification Revision: planner--dev--1.0--patch-64 * planner.el (planner-expand-name): Bugfix: Allow multiple digits in +days or -days specification. modified files: planner.el 2004-04-30 07:36:36 GMT Sacha Chua patch-63 Summary: planner-annotation-use-relative-file Revision: planner--dev--1.0--patch-63 * planner.el (planner-annotation-use-relative-file): New. (planner-annotation-from-file): Change behavior depending on planner-annotation-use-relative-file. modified files: planner.el 2004-04-29 07:16:50 GMT Sacha Chua patch-62 Summary: info update from johnsu01 Revision: planner--dev--1.0--patch-62 modified files: planner.texi 2004-04-29 07:11:49 GMT Sacha Chua patch-61 Summary: New: planner-annotation-from-file-relative Revision: planner--dev--1.0--patch-61 * planner.el (planner-annotation-from-file-relative): New. modified files: planner.el 2004-04-28 15:55:26 GMT Gary V. Vaughan patch-1 Summary: render planner day page calendars with elisp Revision: planner--gary--1.0--patch-1 * planner-calendar.el: New file. new files: .arch-ids/planner-calendar.el.id planner-calendar.el 2004-04-28 05:01:39 GMT Sacha Chua patch-60 Summary: Get BBDB links to resolve properly again Revision: planner--dev--1.0--patch-60 * planner-bbdb.el (planner-resolve-url-table): Add the right protocols. modified files: planner-bbdb.el 2004-04-27 16:06:49 GMT Sacha Chua patch-59 Summary: planner-id: Make automatic updating optional (default: off) Revision: planner--dev--1.0--patch-59 * planner-id.el: Note about new variable. (planner-id-update-automatically): New option controls whether to update linked pages automatically or not. (planner-id-update-tasks-maybe): For convenience. (planner-id-setup): Name the hook function. (planner-mode-hook): Hook in. modified files: planner-id.el 2004-04-27 05:41:38 GMT Sacha Chua patch-58 Summary: Add johnsu01's texinfo manual Revision: planner--dev--1.0--patch-58 * planner.texi: First draft by John Sullivan. new files: .arch-ids/planner.texi.id planner.texi 2004-04-27 02:50:42 GMT Sacha Chua patch-57 Summary: Fix planner diary entries for cal-desk Revision: planner--dev--1.0--patch-57 * planner-diary.el (planner-diary-get-diary-entries): Merge Travis B. Hartwell's patch fixing calendar desk entries. New argument use-cal-desk. (planner-diary-get-cal-desk-entries): Use the new argument of planner-diary-get-diary-entries. modified files: planner-diary.el 2004-04-26 05:13:08 GMT Sacha Chua patch-56 Summary: Allow nil to be entered as a date or plan page name Revision: planner--dev--1.0--patch-56 * planner.el (planner-read-name): Make it easy to return nil. (planner-expand-name): Return nil if "nil" is entered. (planner-create-task-from-info): Work with nil plan pages or dates. (planner-goto-plan-page): Remove unnecessary macro calls. (planner-replan-task): Do the right thing if nil is specified. (planner-copy-or-move-task): Check if date is nil. modified files: planner.el 2004-04-26 03:08:18 GMT Sacha Chua patch-55 Summary: planner-create-{high,medium,low}-priority-task-from-buffer for convenience Revision: planner--dev--1.0--patch-55 * planner.el (planner-create-high-priority-task-from-buffer): New. (planner-create-medium-priority-task-from-buffer): New. (planner-create-low-priority-task-from-buffer): New for your key-binding convenience. modified files: planner.el 2004-04-23 10:44:51 GMT Gary V. Vaughan patch-5 Summary: render planner day page calendars with elisp Revision: emacs-wiki--gary--1.0--patch-5 * planner-calendar.el: New file. new files: .arch-ids/planner-calendar.el.id planner-calendar.el 2004-04-22 02:17:25 GMT Sacha Chua patch-53 Summary: planner-wl: Merge bugfixes from Angus Lee Revision: planner--dev--1.0--patch-53 * planner-wl.el: Merge bugfixes from Angus Lee. modified files: planner-wl.el 2004-04-22 01:53:14 GMT Sacha Chua patch-52 Summary: Bugfix: planner-rmail-browse-url should jump to rmail messages outside excursion Revision: planner--dev--1.0--patch-52 * planner-rmail.el (planner-rmail-browse-url): Bugfix: Move rmail jump to outside excursion. Return message number if found. Thanks to fouvry for help. modified files: planner-rmail.el 2004-04-21 17:12:53 GMT Sacha Chua patch-51 Summary: Bugfix: planner-experimental: planner-remove duplicates should remove dupes on date pages Revision: planner--dev--1.0--patch-51 * planner-experimental.el (planner-remove-duplicates): Bugfix: Work properly with duplicated tasks on a date page. * planner-id.el (planner-id-update-tasks-on-page): Docfix. modified files: planner-experimental.el planner-id.el 2004-04-21 15:05:24 GMT Sacha Chua patch-50 Summary: Bugfix: planner-id.el and saving IDs Revision: planner--dev--1.0--patch-50 * planner-id.el (planner-id-save): Simplify Lisp by using built-in-function. Also solve final newline problem with require-final-newline 'ask. Thanks to Win Treese for reporting bug. modified files: planner-cyclic.el planner-id.el 2004-04-21 14:45:07 GMT Sacha Chua patch-49 Summary: planner-rmail: Improvement: Gracefully deal with missing messages Revision: planner--dev--1.0--patch-49 * planner-rmail.el (planner-rmail-browse-url): Improvement: Gracefully deal with missing messages. Thanks to Frederik Fouvry for the patch. modified files: planner-rmail.el 2004-04-21 14:32:42 GMT Sacha Chua patch-48 Summary: Bugfix: Improve rmail handling of nonexistent messages Revision: planner--dev--1.0--patch-48 * planner-rmail.el (planner-rmail-browse-url): Report the error in the original context. Thanks to Frederik Fouvry for idea/patch. modified files: planner-rmail.el 2004-04-21 13:54:18 GMT Sacha Chua patch-47 Summary: planner-gnus: Go directly to message; planner-rmail: elisp tweak Revision: planner--dev--1.0--patch-47 * planner-gnus.el (planner-gnus-browse-url): NOTE: No longer prompt for number of messages. Try to go directly to the message instead. * planner-rmail.el (planner-rmail-browse-url): Remove unnecessary `rmail-first-message'. modified files: planner-gnus.el planner-rmail.el 2004-04-20 17:24:33 GMT Sacha Chua patch-46 Summary: Feature: planner-search-notes-with-body Revision: planner--dev--1.0--patch-46 * planner.el (planner-search-notes-internal): Can include body. (planner-search-notes-with-body): New. (planner-search-notes): Can include body. Thanks to cpchan for the suggestion. modified files: planner.el 2004-04-20 17:10:35 GMT Sacha Chua patch-45 Summary: Set list-diary-entries-hook for planner-cyclic-get-cyclic-tasks Revision: planner--dev--1.0--patch-45 * planner-cyclic.el (planner-cyclic-get-cyclic-tasks): Force `list-diary-entries-hook' to a canonical value. Thanks to cpchan for pointing this out. modified files: planner-cyclic.el 2004-04-20 13:05:37 GMT Sacha Chua patch-44 Summary: Bugfix: planner-cyclic error checking Revision: planner--dev--1.0--patch-44 * planner-cyclic.el (planner-cyclic-create-task-maybe): Add check to make sure string looks like a task. (planner-cyclic-create-tasks-maybe): Make sure this page has a page name. Thanks to Charles Philip Chan for pointing both bugs out. modified files: planner-cyclic.el 2004-04-20 13:00:59 GMT Sacha Chua patch-43 Summary: Obey command passed to planner-find-file Revision: planner--dev--1.0--patch-43 * planner.el (planner-find-file): Actually obey command. Thanks to Charles Philip Chan for pointing this out. modified files: planner.el 2004-04-20 11:40:45 GMT Sacha Chua patch-42 Summary: Bugfix: return t all the time in browse-url functions Revision: planner--dev--1.0--patch-42 * planner-*.el (planner-*-browse-url): Bugfix: Return t all the time. modified files: planner-bbdb.el planner-erc.el planner-lisp.el planner-vm.el planner-w3m.el planner-wl.el planner.el 2004-04-20 04:14:30 GMT Sacha Chua patch-41 Summary: Bugfix: planner-bbdb slashes optional, planner.el publishing (move tags first), planner-copy-or-move-task accepts nil Revision: planner--dev--1.0--patch-41 * planner.el (planner-publishing-markup): Bugfix: Process tags before the rest of the stuff because things in need to be read-only. * planner-bbdb.el: Make slashes optional. * planner.el (planner-copy-or-move-task): Correctly work when "nil" is specified. Thanks to Ray Fix for bringing this to my attention. modified files: planner-bbdb.el planner.el 2004-04-17 15:36:17 GMT Sacha Chua patch-40 Summary: Rewrite planner-tasks-equal-p for clarity Revision: planner--dev--1.0--patch-40 * planner.el (planner-tasks-equal-p): Rewrite for clarity by using descriptive names. Thanks to Frederik for feedback. modified files: planner.el 2004-04-17 15:26:19 GMT Sacha Chua patch-39 Summary: NOTE: Feature: limit for planner-search-notes (call with C-u) Revision: planner--dev--1.0--patch-39 * planner.el (planner-list-daily-files,planner-get-day-pages): New option EXCLUDE-TEMP ignores unsaved buffers. (planner-search-notes-internal, planner-search-notes): Add LIMIT. NOTE: New feature: limit for planner-search-notes if called with universal prefix. modified files: planner.el 2004-04-17 14:53:08 GMT Sacha Chua patch-38 Summary: Bugfix: Preserve project and mode in index Revision: planner--dev--1.0--patch-38 * planner-experimental.el (planner-index): AHA! Properly use emacs-wiki-project and highlight properly. (emacs-wiki-change-project) has no effect if we change to planner-mode, as changing mode zaps all the local variables. Thanks to ephrem for reporting the bug. (planner-generate-index): NOTE: Indexes dates in reverse order. * planner-notes-index.el (planner-notes-index): Preserve project. modified files: planner-experimental.el planner-notes-index.el 2004-04-17 14:08:33 GMT Sacha Chua patch-37 Summary: Bugfix: Allow any status in planner-find-task Revision: planner--dev--1.0--patch-37 * planner.el (planner-find-task): Bugfix: Allow any status. Thanks to Ephrem for pointing out the bug. (planner-publishing-markup): Add note about planner-marks-regexp. (planner-marks-regexp): Add note about planner-publishing-markup. modified files: planner.el 2004-04-16 03:57:23 GMT Sacha Chua patch-36 Summary: Bugfix: Sort diary entries Revision: planner--dev--1.0--patch-36 * planner-diary.el (planner-diary-get-diary-entries): Sort diary entries. modified files: planner-diary.el 2004-04-16 02:57:00 GMT Sacha Chua patch-35 Summary: Bugfix: planner-diary should use fancy-diary-display Revision: planner--dev--1.0--patch-35 * planner-diary.el (planner-diary-get-diary-entries): Bugfix: Make sure fancy-diary-display is used. Do not squelch messages; this can lead to mysterious problems. modified files: planner-diary.el 2004-04-15 15:34:18 GMT Sacha Chua patch-34 Summary: Bugfix: planner-rss is extra-paranoid about missing information Revision: planner--dev--1.0--patch-34 * planner-rss.el (planner-rss-add-note): Extra paranoia for stuff that is missing. Guarded against nil inserts. modified files: planner-rss.el 2004-04-15 14:09:26 GMT Sacha Chua patch-33 Summary: Important bugfix: Properly update task Revision: planner--dev--1.0--patch-33 * planner.el (planner-copy-or-move-task): Important bugfix: Properly update task. Correct bug introduced in patch-28. modified files: planner.el 2004-04-15 13:20:14 GMT Sacha Chua patch-32 Summary: Bugfix: planner-list-daily-files and other buffers, planner-gnus and URLs Revision: planner--dev--1.0--patch-32 * planner-gnus.el (planner-gnus-browse-url): Make sure planner-gnus always handles gnus: URLs. * planner.el (planner-list-daily-files): Make sure the page has a name. modified files: planner-gnus.el planner.el 2004-04-15 03:45:53 GMT Sacha Chua patch-31 Summary: Change pending task mark to "P" Revision: planner--dev--1.0--patch-31 * planner.el (planner-publishing-markup): Accept P as task status. (planner-marks-regexp): Accept P as task status. (planner-renumber-tasks): Sort pending, then delegated, then completed, then cancelled tasks. (planner-markup-task): Mark up pending tasks. (planner-task-pending): Change pending task mark to P. Thanks to Ephrem for the feature request. * planner.el (planner-list-unfinished-tasks): Consider cancelled tasks finished. modified files: planner.el 2004-04-15 03:38:01 GMT Sacha Chua patch-30 Summary: Bugfix: duplicate planner-task-cancelled, experimental planner-jump-to-linked-note Revision: planner--dev--1.0--patch-30 * planner.el: Remove duplicate planner-task-cancelled. (planner-jump-to-linked-note): Promote from planner-experimental.el. Thanks to Martin Morgan for pointing these out. (planner-file-alist): Move to emacs-wiki layer section. modified files: planner-experimental.el planner.el 2004-04-14 17:23:11 GMT Sacha Chua patch-29 Summary: Bugfix: Save restriction in planner-copy-or-move-task Revision: planner--dev--1.0--patch-29 * planner.el (planner-copy-or-move-task): Save restriction now that we do fancy things in planner-copy-or-move-region. This fixes the problem of interactively calling planner-copy-or-move-region with a marked region. modified files: planner.el 2004-04-14 17:11:08 GMT Sacha Chua patch-28 Summary: Feature: planner-add-task-at-end-flag Revision: planner--dev--1.0--patch-28 * planner.el (planner-add-task-at-end-flag): New. (planner-create-task-from-info): Create at creation point, wherever that is. (planner-read-name, planner-file-alist, planner-page-file): Docfix. Satisfy checkdoc. (planner-seek-task-creation-point): New. (planner-copy-or-move-task): Create at creation point. (planner-update-task): Create at creation point. (planner-copy-or-move-region): Obey planner-add-task-at-end-flag. modified files: planner.el 2004-04-14 15:50:13 GMT Sacha Chua patch-27 Summary: Add error-checking to planner-cyclic Revision: planner--dev--1.0--patch-27 * planner-cyclic.el (planner-cyclic-get-cyclic-tasks): Remove nil elements. (planner-cyclic-generate-task): Check if task is correctly parsed. (planner-cyclic-create-tasks-maybe): Check if task-string is non-nil. modified files: planner-cyclic.el 2004-04-13 08:47:25 GMT Sacha Chua patch-26 Summary: Enhancement: planner-rmail scans backward Revision: planner--dev--1.0--patch-26 * planner-rmail.el (planner-rmail-browse-url): Scan backward for efficiency. Also, return -1 if not found. Thanks to Frederik Fouvry for the suggestion. modified files: planner-rmail.el 2004-04-13 08:45:32 GMT Sacha Chua patch-25 Summary: Bugfix: planner-gnus: work with cached articles Revision: planner--dev--1.0--patch-25 * planner-gnus.el (planner-gnus-browse-url): Work with cached articles. Thanks to John Sullivan for pointing this out. (planner-gnus-annotation): New for convenience. (planner-annotation-functions): Use planner-gnus-annotation. modified files: planner-gnus.el 2004-04-11 08:17:18 GMT Sacha Chua patch-24 Summary: NOTE: New function planner-task-cancelled bound to C-c C-S-x by default Revision: planner--dev--1.0--patch-24 * planner.el (planner-mode-map): Add keyboard shortcut for planner-task-cancelled. (planner-install-extra-task-keybindings): Add keyboard shortcut for planner-task-cancelled. (planner-task-cancelled): New. modified files: planner.el 2004-04-11 08:16:11 GMT Sacha Chua patch-23 Summary: Bugfix: Correctly switch notes indices into planner mode Revision: planner--dev--1.0--patch-23 * planner-notes-index.el (planner-notes-index): Bugfix: correctly switch into planner mode. modified files: planner-notes-index.el 2004-04-11 06:37:22 GMT Sacha Chua patch-22 Summary: Enhancement: Always create planner-directory Revision: planner--dev--1.0--patch-22 * planner.el (planner-find-file): Always create planner-directory. (planner-goto): Call planner-find-file. modified files: planner.el 2004-04-11 06:36:11 GMT Sacha Chua patch-21 Summary: Bugfix: Refontify after adding task IDs to all tasks Revision: planner--dev--1.0--patch-21 * planner-id.el: Docfix: Add URL. (planner-id-add-task-id-to-all): Bugfix: Refontify after adding task IDs. modified files: planner-id.el 2004-04-07 11:24:38 GMT Sacha Chua patch-20 Summary: Resolve windmove keybinding conflict Revision: planner--dev--1.0--patch-20 * planner.el (planner-install-extra-context-keybindings): Move windmove-conflicting keybindings to this function. Thanks to TerryP for pointing this out. modified files: planner.el 2004-04-07 10:53:00 GMT Sacha Chua patch-19 Summary: Context-sensitive keyboard shortcuts (S-up, S-down, S-right) Revision: planner--dev--1.0--patch-19 * planner.el (planner-mode-map): New keybindings: shift up (move up), shift down (move down), and shift right (follow link). NOTE: They might be more convenient than the current defaults. (planner-jump-to-link): New. (planner-move-up): New. (planner-move-down): New. (planner-current-note-info): Save excursion. (planner-update-task): Save excursion. modified files: planner.el 2004-04-07 05:59:39 GMT Sacha Chua patch-18 Summary: Save position and restriction for planner-update-note Revision: planner--dev--1.0--patch-18 * planner-experimental.el (planner-update-note): Save position, restriction, and window excursion so that we don't freak pll out. modified files: planner-experimental.el 2004-04-05 16:08:13 GMT Sacha Chua patch-17 Summary: Make date optional for tasks. Revision: planner--dev--1.0--patch-17 * planner.el (planner-create-task-from-info): Make date optional. (planner-create-task-from-buffer): Make date optional. Thanks to Alan Schussman and emacs-wiki-discuss for the suggestion. You can now specify a non-date as the date to make a task that is not associated with any date. Warning: Unscheduled tasks might be forgotten. modified files: planner.el 2004-04-05 15:38:11 GMT Sacha Chua patch-16 Summary: planner-rmail: Return message number Revision: planner--dev--1.0--patch-16 * planner-rmail.el (planner-rmail-browse-url): Return message number according to Frederik Fouvry's suggestion. modified files: planner-rmail.el 2004-04-05 04:57:03 GMT Sacha Chua patch-15 Summary: Preliminary support for clocking out when a task is finished Revision: planner--dev--1.0--patch-15 * planner-timeclock.el: Preliminary support for clocking out when a task is finished. Thanks to dto for pointing this out. modified files: planner-timeclock.el 2004-04-05 04:45:26 GMT Sacha Chua patch-14 Summary: Add prefix arg FORCE to planner-id-update-tasks-on-page Revision: planner--dev--1.0--patch-14 * planner-id.el (planner-id-update-tasks-on-page): Add prefix argument to force all tasks to be updated, including completed and cancelled tasks. modified files: planner-id.el 2004-04-05 02:25:36 GMT Sacha Chua patch-13 Summary: Do not use string> Revision: planner--dev--1.0--patch-13 * planner-experimental.el (planner-remove-duplicates): Do not use string>. (Why isn't that in subr? Pfft.) Thanks to Martin Stemplinger for pointing this out. * planner-cyclic.el (planner-cyclic-create-tasks-maybe): Do not use string>. (Why isn't that in subr? Pfft.) Thanks to Martin Stemplinger for pointing this out. modified files: planner-cyclic.el planner-experimental.el 2004-04-04 10:29:29 GMT Sacha Chua patch-12 Summary: Condition-case keybindings, require easymenu Revision: planner--dev--1.0--patch-12 * planner-schedule.el: Wrap a condition-case around key definitions. Require easymenu. * planner-timeclock.el: Wrap a condition-case around key definitions. Require easymenu. * planner.el: Require easymenu. modified files: planner-schedule.el planner-timeclock.el planner.el 2004-04-04 10:08:05 GMT Sacha Chua patch-11 Summary: Add note about where to get timeclock.el Revision: planner--dev--1.0--patch-11 * planner-timeclock.el: Add note about where to get timeclock.el modified files: planner-timeclock.el 2004-04-04 10:05:36 GMT Sacha Chua patch-10 Summary: Bugfix: planner-replan-task and tasks without plan pages Revision: planner--dev--1.0--patch-10 * planner.el (planner-replan-task): Correctly work with tasks with no associated plan page. Thanks to pll for pointing this out. modified files: planner.el 2004-04-04 09:57:12 GMT Sacha Chua patch-9 Summary: Support arbitrary mailboxes for planner-rmail Revision: planner--dev--1.0--patch-9 * planner-rmail.el (planner-rmail-annotation-from-mail): Allow arbitrary mailboxes. (planner-rmail-browse-url): Open arbitrary mailboxes, but retain backward compatibility. Thanks to Frederik Fouvry for pointing this out. modified files: planner-rmail.el 2004-03-31 15:10:20 GMT Sacha Chua patch-8 Summary: Bugfix: Merge Nafai's patch correcting planner-diary.el Revision: planner--dev--1.0--patch-8 * planner-diary.el (planner-diary-insert-cal-desk): Merge Nafai's patch correcting a typo. (planner-diary-use-public-diary): Merge Nafai's patch correcting a typo. modified files: planner-diary.el 2004-03-30 05:47:08 GMT Sacha Chua patch-7 Summary: Remove planner-notes.el from distribution Revision: planner--dev--1.0--patch-7 * planner-notes.el: Remove from distribution as Thomas Gehrlein requests. (He's not quite sure what he wants it to do.) removed files: .arch-ids/planner-notes.el.id planner-notes.el 2004-03-30 05:40:48 GMT Sacha Chua patch-6 Summary: Bugfix: Invalid regular expression in planner-id.el Revision: planner--dev--1.0--patch-6 * planner-id.el (planner-id-update-tasks-on-page): Change invalid regular expression. Thanks to pll for pointing this out. modified files: planner-id.el 2004-03-30 04:55:34 GMT Sacha Chua patch-5 Summary: Docfix: planner-create-task-from-buffer. NOTE: default behavior asks for plan page after creating a task Revision: planner--dev--1.0--patch-5 * planner.el (planner-create-task-from-buffer): Update documentation to reflect new behavior. NOTE: By default, planner-create-task-from-buffer now assumes that you want to associate the task with a plan page. This keeps in line with planner's original philosophy that most (if not all) of your tasks should be part of a plan. modified files: planner.el 2004-03-30 04:46:45 GMT Sacha Chua patch-4 Summary: Bugfix: Add planner-history-list, reorganize reading functions into Convenience section Revision: planner--dev--1.0--patch-4 * planner.el: Moved planner-read-name, planner-read-non-date-page, planner-default-page to Convenience section. (planner-history-list): Bugfix: New. modified files: planner.el 2004-03-30 04:38:43 GMT Sacha Chua patch-3 Summary: Split schedule export functions into planner-export-diary.el Revision: planner--dev--1.0--patch-3 * planner-export-diary.el, planner.el: Split off schedule-related functions from planner.el and placed them in planner-export-diary.el, renaming to avoid namespace conflicts with planner-diary.el. Add documentation in comments. new files: .arch-ids/planner-export-diary.el.id planner-export-diary.el modified files: planner.el 2004-03-30 04:19:25 GMT Sacha Chua patch-2 Summary: Updated planner-diary.el from Thomas Gehrlein Revision: planner--stable--1.0--patch-2 * planner-diary.el: Update from Thomas Gehrlein: version 1.0. Some patches for documentation. Passes checkdoc now. modified files: planner-diary.el 2004-03-26 08:51:44 GMT Sacha Chua patch-1 Summary: Update wiki project and save all buffers during plan Revision: planner--dev--1.0--patch-1 * planner.el (plan): Paranoia: update wiki project in case you're forgotten to do so, and save all the buffers after planning. modified files: planner.el 2004-03-25 08:21:52 GMT Sacha Chua patch-148 Summary: No need to escape URLs in planner-erc as emacs-wiki-markup-link handles that now Revision: emacs-wiki--sacha--1.0--patch-148 * planner-erc.el (planner-erc-annotation-from-erc): No more need to escape URLs here, as emacs-wiki-escape-url does that automatically. modified files: planner-erc.el 2004-03-25 08:18:37 GMT Sacha Chua patch-147 Summary: Add planner-replan-task so that you can change the plan page of created tasks Revision: emacs-wiki--sacha--1.0--patch-147 * planner.el (planner-copy-or-move-task): Allow replanning. (planner-replan-task): New. modified files: planner.el 2004-03-25 06:03:12 GMT Sacha Chua patch-146 Summary: Rename planner-insinuate-diary to planner-diary-insinuate Revision: emacs-wiki--sacha--1.0--patch-146 * planner-diary.el (planner-diary-insinuate): Renamed from (planner-insinuate-diary). modified files: planner-diary.el 2004-03-25 04:34:56 GMT Sacha Chua patch-144 Summary: Updated planner-diary.el from Thomas Gehrlein (canonical version 0.6) Revision: emacs-wiki--sacha--1.0--patch-144 * planner-diary.el: Thomas Gehrlein's 0.6 update: Support for cal-desk, excluding appointments. modified files: planner-diary.el 2004-03-25 01:47:09 GMT Sacha Chua patch-143 Summary: Correct numbering for tasks with no dates Revision: emacs-wiki--sacha--1.0--patch-143 * planner.el (planner-renumber-tasks): Correct renumbering for tasks with no dates. modified files: planner.el 2004-03-24 11:30:54 GMT Sacha Chua patch-142 Summary: Preliminary support for irc:// URLs Revision: emacs-wiki--sacha--1.0--patch-142 * planner.el (planner-encode-url): New. * planner-erc.el (planner-erc-annotation-from-erc): Preliminary support for irc:// URLs as specified by http://ftp.ics.uci.edu/pub/ietf/uri/draft-mirashi-url-irc-01.txt modified files: planner-erc.el planner.el 2004-03-24 08:52:46 GMT Sacha Chua patch-141 Summary: Bugfix: planner-renumber-tasks should not error for incomplete tasks Revision: emacs-wiki--sacha--1.0--patch-141 * planner.el (planner-renumber-tasks): Do not error for incomplete tasks. modified files: planner.el 2004-03-24 07:04:57 GMT Sacha Chua patch-140 Summary: Actually add planner-diary.el Revision: emacs-wiki--sacha--1.0--patch-140 new files: .arch-ids/remember-diary.el.id remember-diary.el 2004-03-24 06:52:33 GMT Sacha Chua patch-139 Summary: Do not update cancelled/completed tasks. Minor optimizations for renumbering Revision: emacs-wiki--sacha--1.0--patch-139 * planner.el (planner-renumber-tasks): Unlet planner-use-font-lock. Try to optimize handling for plan pages. (planner-renumber-notes): Unlet planner-use-font-lock. * planner-id.el (planner-id-update-tasks-on-page): Do not update cancelled or completed tasks. modified files: planner-id.el planner.el 2004-03-23 09:34:41 GMT Sacha Chua patch-135 Summary: Correct documentation note for planner-gnus.el Revision: emacs-wiki--sacha--1.0--patch-135 * planner-gnus.el: Correct documentation note about planner-gnus-insinuate. Thanks to johnsu01 for pointing this out. modified files: planner-gnus.el 2004-03-23 01:29:11 GMT Sacha Chua patch-133 Summary: Do not move cancelled tasks Revision: emacs-wiki--sacha--1.0--patch-133 * planner.el (planner-copy-or-move-task): Do not move cancelled tasks. (planner-copy-or-move-region): Do not move cancelled tasks. modified files: planner.el 2004-03-23 01:24:20 GMT Sacha Chua patch-132 Summary: Create cyclic tasks only for present/future; add "C" as status marker for cancelled tasks Revision: emacs-wiki--sacha--1.0--patch-132 * planner-cyclic.el (planner-cyclic-create-tasks-maybe): Only create tasks for present or future dates. * planner.el (planner-publishing-markup): Add "C" as a status marker for cancelled tasks. (planner-marks-regexp): Add "C" as a status marker for cancelled tasks. (planner-renumber-tasks): Move cancelled tasks all the way to the bottom. (planner-cancelled-task-face): New. (planner-highlight-tasks): Highlight cancelled tasks. * planner.el (planner-raise-task): planner-raise-task now works over blocks of tasks. You can raise a task to the previous block or lower it to the next one. Task blocks are delimited by non-task lines. modified files: planner-cyclic.el planner.el 2004-03-21 15:07:06 GMT Sacha Chua patch-131 Summary: planner-raise-task works over blocks of tasks Revision: emacs-wiki--sacha--1.0--patch-131 * planner.el (planner-raise-task): planner-raise-task now works over blocks of tasks. You can raise a task to the previous block or lower it to the next one. Task blocks are delimited by non-task lines. modified files: planner.el 2004-03-19 06:56:16 GMT Sacha Chua patch-130 Summary: Save restriction for planner-update-note Revision: emacs-wiki--sacha--1.0--patch-130 * planner-experimental.el (planner-update-note): Save restriction. Thanks to Jody Klymak for pointing this out. modified files: planner-experimental.el 2004-03-19 06:55:43 GMT Sacha Chua patch-129 Summary: Add FORCE-DAYS optional argument to plan. Revision: emacs-wiki--sacha--1.0--patch-129 * planner.el (plan): Pay attention to FORCE-DAYS. modified files: planner.el 2004-03-18 13:07:31 GMT Sacha Chua patch-128 Summary: Add PLANNER-README Revision: emacs-wiki--sacha--1.0--patch-128 * PLANNER-README: Add to source control. I keep forgetting the file. new files: .arch-ids/PLANNER-README.id PLANNER-README 2004-03-18 09:26:23 GMT Sacha Chua patch-125 Summary: planner-read-name Revision: emacs-wiki--sacha--1.0--patch-125 * planner.el (planner-read-name): New. Bugfix, thanks to johnsu01 for pointing this out. modified files: planner.el 2004-03-18 09:18:01 GMT Sacha Chua patch-124 Summary: Remove duplicate tasks from day pages when M-x planner-remove-duplicates is invoked on a plan page Revision: emacs-wiki--sacha--1.0--patch-124 * planner-experimental.el (planner-remove-duplicates): Intelligently remove duplicates from day pages. You can invoke this from a plan page to zap most duplicate tasks. * planner.el (planner-find-task): New optional argument POINT defines starting position. modified files: planner-experimental.el planner.el 2004-03-17 03:21:34 GMT Sacha Chua patch-119 Summary: Documentation fix for planner-notes-index: Attribute is limit, not recent. Revision: emacs-wiki--sacha--1.0--patch-119 * planner-notes-index.el: Documentation fix; should be limit, not recent. modified files: planner-notes-index.el 2004-03-16 04:55:25 GMT Sacha Chua patch-118 Summary: Restore planner-annotation-from-planner-note Revision: emacs-wiki--sacha--1.0--patch-118 * planner.el (planner-annotation-functions): Add planner-annotation-from-planner-note. (planner-annotation-from-planner-note): Remove redundant check. * emacs-wiki.el (emacs-wiki-visit-link): Deal with bare tags. modified files: emacs-wiki.el planner.el 2004-03-16 04:43:46 GMT Sacha Chua patch-117 Summary: Emacs21 non-CVS bugfix wrt task highlighting, fixed by moving tasks, notes highlighting to before emacs-wiki Revision: emacs-wiki--sacha--1.0--patch-117 * emacs-wiki.el (emacs-wiki-before-highlight-buffer-hook): New. (emacs-wiki-highlight-region): Call emacs-wiki-before-highlight-buffer-hook. * planner.el (planner-mode): Move tasks, notes highlighting to _before_ emacs-wiki highlighting. Kludge so that emacs21 non-CVS renders things properly. modified files: emacs-wiki.el planner.el 2004-03-16 03:47:05 GMT Sacha Chua patch-115 Summary: Make non-reactive tasks easier to schedule; swap sense of C-u on planner-create-task-from-buffer Revision: emacs-wiki--sacha--1.0--patch-115 * planner.el (planner-create-task-from-buffer): User-visible change: Swap sense of C-u. You now need to press C-u to associate a task only with a date page (punish reactive tasks!). By default, tasks are associated with the current plan page or the last plan page selected from the minibuffer. (planner-default-page): New. modified files: planner.el 2004-03-16 02:49:55 GMT Sacha Chua patch-114 Summary: Fix planner-cyclic bug by not anchoring regex at start of string in planner-task-info-from-string Revision: emacs-wiki--sacha--1.0--patch-114 * planner.el (planner-task-info-from-string): Do not anchor regular expression at start of string so that planner-cyclic tasks are more flexible. modified files: planner.el 2004-03-15 07:05:13 GMT Sacha Chua patch-109 Summary: planner-annotation-from-info Revision: emacs-wiki--sacha--1.0--patch-109 * planner.el (planner-annotation-from-info): New. Thanks to Yvonne Thomson for contributing this. modified files: planner.el 2004-03-14 16:08:37 GMT Sacha Chua patch-104 Summary: Add planner-lisp.el for interactive Emacs Lisp functions Revision: emacs-wiki--sacha--1.0--patch-104 * planner-lisp.el: New. new files: .arch-ids/planner-lisp.el.id planner-lisp.el 2004-03-14 14:51:52 GMT Sacha Chua patch-103 Summary: Revision: emacs-wiki--sacha--1.0--patch-103 * planner.el (plan): Create `planner-directory' automatically if not yet there. modified files: planner.el 2004-03-14 14:40:56 GMT Sacha Chua patch-102 Summary: Bugfix Revision: emacs-wiki--sacha--1.0--patch-102 * planner.el (planner-find-task): Bugfix: allow more than one digit for the priority. Oops! modified files: planner.el 2004-03-13 06:22:40 GMT Sacha Chua patch-100 Summary: Fix infinite loop in planner-bbdb.el Revision: emacs-wiki--sacha--1.0--patch-100 * planner-bbdb.el (planner-bbdb-annotation-from-bbdb): Fix infinite loop. Thanks to johnsu01 for pointing this out. modified files: planner-bbdb.el 2004-03-12 17:24:13 GMT Sacha Chua patch-98 Summary: Docfix in planner.el - remove mention of planner-calendar.el Revision: emacs-wiki--sacha--1.0--patch-98 * planner.el: Remove mention of planner-calendar.el and add note about `planner-calendar-insinuate'. Thanks to kanaldrache for pointing this out. modified files: planner.el 2004-03-12 15:12:25 GMT Sacha Chua patch-97 Summary: Improve annotation matching Revision: emacs-wiki--sacha--1.0--patch-97 * planner.el (planner-create-task): Improve annotation matching. modified files: planner.el 2004-03-12 07:12:20 GMT Sacha Chua patch-94 Summary: planner-cyclic: Cyclic task support. Revision: emacs-wiki--sacha--1.0--patch-94 * planner-cyclic.el: New. new files: .arch-ids/planner-cyclic.el.id planner-cyclic.el test/.arch-ids/planner-cyclic-test.el.id test/planner-cyclic-test.el modified files: planner.el test/planner-test.el 2004-03-12 05:09:11 GMT Sacha Chua patch-91 Summary: Do not change windows when navigating day pages with yesterday/tomorrow Revision: emacs-wiki--sacha--1.0--patch-91 * planner.el (planner-goto-yesterday): Do not change windows. (planner-goto-tomorrow): Do not change windows. (planner-goto-previous-daily-page): Do not change windows. (planner-goto-next-daily-page): Do not change windows. modified files: planner.el 2004-03-12 03:42:48 GMT Sacha Chua patch-88 Summary: Understand dates of the form +1 or -1 Revision: emacs-wiki--sacha--1.0--patch-88 * planner.el (planner-expand-name): Understand dates of the form "+1" or "-1" as offsets from today. Thanks to k-man on #emacs for the suggestion. modified files: planner.el 2004-03-12 02:39:19 GMT Sacha Chua patch-87 Summary: Work with parens in the task description Revision: emacs-wiki--sacha--1.0--patch-87 * planner.el (planner-task-info-from-string): Work with parens in the task description. Test suite at test/planner-test.el . (planner-create-task): Improve annotation matching. * test/planner-test.el: New. new files: test/.arch-ids/planner-test.el.id test/planner-test.el modified files: planner.el 2004-03-11 14:13:20 GMT Sacha Chua patch-86 Summary: Minor bugfix. Do not error if tasks are at end of buffer. Revision: emacs-wiki--sacha--1.0--patch-86 * planner.el (planner-renumber-tasks): Do not error if tasks are at end of buffer. modified files: planner.el 2004-03-11 13:58:38 GMT Sacha Chua patch-85 Summary: Further planner-renumber-tasks optimization Revision: emacs-wiki--sacha--1.0--patch-85 * planner.el (planner-renumber-tasks): Further optimization. Don't use a regular expression to check for further tasks. Use character comparison instead. This should trim off another second or two. modified files: planner.el 2004-03-11 13:43:46 GMT Sacha Chua patch-84 Summary: Optimize sort, assuming sort is stable Revision: emacs-wiki--sacha--1.0--patch-84 * planner.el (planner-renumber-tasks): Optimize sort. Assumes sort is stable, which it appears to be under CVS Emacs. modified files: planner.el 2004-03-11 13:21:30 GMT Sacha Chua patch-83 Summary: Merged John Wiegley's emacs-wiki changes in. Small bugfixes. Revision: emacs-wiki--sacha--1.0--patch-83 * planner.el (planner-in-progress-task-face): Remove dupe. Thanks to Florian Lanthaler for pointing this out. * emacs-wiki.el (emacs-wiki-page-date): Remove parameter, correct docstring. (emacs-wiki-numbered-tag): Use ID attribute instead of unclosed * emacs-wiki.el: Merged John Wiegley's patch in preparation for flexible publishing. modified files: emacs-wiki.el planner.el 2004-03-11 08:44:48 GMT Sacha Chua patch-82 Summary: Bugfixes. Also, emacs-wiki no longer errors on publish--just warns Revision: emacs-wiki--sacha--1.0--patch-82 * emacs-wiki.el (emacs-wiki-eval-lisp): Warn if error, but do not stop. Thanks to Mark Triggs for the patch. * planner.el (planner-in-progress-task-face): No :slant in XEmacs; using :bold instead. Thanks to Mario Peter for the patch. * planner.el (planner-create-task): Work with new emacs-wiki-make-link. modified files: emacs-wiki.el planner.el 2004-03-11 02:32:24 GMT Sacha Chua patch-81 Summary: Emacs20 compatibility Revision: emacs-wiki--sacha--1.0--patch-81 * remember.el (remember-clipboard): Use compatibility function. * planner.el (planner-list-daily-files): Remove mapc call. (planner-tasks-tag): Remove mapc call. (planner-list-tasks-with-status): Remove mapc call. (planner-extract-tasks): Remove mapc call. (planner-search-notes-internal): add-to-list in emacs20 has only two parameters. Remove need for three parameters by reversing the list. (planner-extract-tasks): Remove mapc call. * emacs-wiki.el (emacs-wiki-make-faces): Remove mapc call. Files now compile cleanly under Emacs21 and Emacs20 (except for emacs-wiki, which still has lots of warnings.) modified files: emacs-wiki.el planner.el remember.el 2004-03-10 05:03:18 GMT Sacha Chua patch-80 Summary: Deal with lines that do not have nicks, like the ERC prompt. Revision: emacs-wiki--sacha--1.0--patch-80 * planner-erc.el (planner-erc-annotation-from-erc): Deal with lines that do not have nicks. modified files: planner-erc.el 2004-03-10 04:58:14 GMT Sacha Chua patch-79 Summary: planner-erc provides annotation functions for ERC buffers Revision: emacs-wiki--sacha--1.0--patch-79 * planner-erc.el: New. new files: .arch-ids/planner-erc.el.id planner-erc.el 2004-03-10 03:06:46 GMT Sacha Chua patch-78 Summary: Remove 'cl dependency of emacs-wiki.el. Add planner-search-notes-next/previous-match. Revision: emacs-wiki--sacha--1.0--patch-78 * emacs-wiki.el (emacs-wiki-visit-link): Hardcode emacs-wiki-after-save-hook in so that we can avoid using gensym. (emacs-wiki-refresh-buffers): New function updates all project buffers. (add-once-hook): Deleted. * planner.el (planner-search-notes-internal): Sort entries correctly even if reverse-chronologically arranged. (planner-search-notes-buffer): New. Save buffer so that we can go to the previous and next matches. (planner-search-notes): Save buffer in planner-search-notes-buffer so that we can go to the next and previous matches. * planner-experimental.el (planner-search-notes-next-match): New. (planner-search-notes-previous-match): New. * emacs-wiki.el (add-once-hook): Use make-symbol instead of gensym. modified files: planner-experimental.el planner.el 2004-03-09 08:58:18 GMT Sacha Chua patch-76 Summary: Renamed p-i-c to planner-calendar-insinuate to be more consistent Revision: emacs-wiki--sacha--1.0--patch-76 * planner.el (planner-calendar-insinuate): Renamed from planner-insinuate-calendar to be more consistent with other functions. Thanks to Yvonne Thomson for pointing this out. * planner-diary.el: Clarified documentation. Adopted it for my own use, so if this breaks, I'll be one of those to complain loudly. modified files: planner-diary.el planner.el 2004-03-08 16:01:23 GMT Sacha Chua patch-73 Summary: Added planner-notes-index.el, fixed emacs-wiki escape/unescape Revision: emacs-wiki--sacha--1.0--patch-73 * planner-notes-index.el: New file. View a list of your notes using the interactive functions, or publish indexes using emacs-wiki tags. See comments for more details. * emacs-wiki.el (emacs-wiki-link-escape): Finally fix this broken function. I must have been really lucky not to have run into problems with this before. Apologies to people bemused by this bug! (emacs-wiki-link-unescape): Same as emacs-wiki-link-escape. (emacs-wiki-highlight-link): Unescape link text when displayed. Tested with notes-index, which had lots of links with brackets. (emacs-wiki-wiki-visible-name): Unescape further in titles. (emacs-wiki-make-link): Escape # in titles. The files I touched compile cleanly under Emacs CVS and XEmacs, with the exception of emacs-wiki.el. I still have to untangle it. Again, apologies for small, careless bugs. Would love to hear from anyone with more experience writing test suites for Emacs programs! Also, have to get the hang of testcover.el ... =) * planner-rmail.el (rmail): Add missing require. * planner.el (planner-create-task-from-info): Fix free variable. new files: .arch-ids/planner-notes-index.el.id planner-notes-index.el modified files: emacs-wiki.el planner-rmail.el planner.el 2004-03-08 10:36:00 GMT Sacha Chua patch-72 Summary: Bugfix in planner task creation, thanks to Nafai for pointing this out Revision: emacs-wiki--sacha--1.0--patch-72 * planner.el (planner-format-task): Fix typo. Thanks to Nafai for pointing this out! (planner-create-task): Fix dangling from. (planner-create-task-from-info): Fix bug for creating with plan-page set to a date page. (planner-create-task-from-buffer): Fix bug for creating from a date page. modified files: planner.el 2004-03-08 06:48:22 GMT Sacha Chua patch-71 Summary: Do not fold case when checking links. Revision: emacs-wiki--sacha--1.0--patch-71 * planner.el (planner-format-task): Actually observe LINK. * emacs-wiki.el (emacs-wiki-make-link): Do not fold case. modified files: emacs-wiki.el planner.el 2004-03-08 06:11:59 GMT Sacha Chua patch-70 Summary: Added planner-wl.el Revision: emacs-wiki--sacha--1.0--patch-70 * planner-wl.el: New file. Thanks to Yvonne Thomson for contributing this to planner. new files: .arch-ids/planner-wl.el.id planner-wl.el 2004-03-08 05:51:49 GMT Sacha Chua patch-69 Summary: With a prefix, planner-create-task-from-buffer prompts for a plan page. Also, planner-rss has category note. Revision: emacs-wiki--sacha--1.0--patch-69 * planner.el (planner-create-task-from-info): Pay attention to plan and date. (planner-create-task-from-buffer): With a prefix, prompt for a plan page. If a plan page is specified and this is not equal to the current annotation, move annotation into the task description. (planner-read-non-date-page): New defun. (planner-create-task): Add plan-page. * planner-rss.el (planner-rss-add-note): Add category link. new files: .arch-ids/schedule.el.id .arch-ids/timeclock.el.id schedule.el timeclock.el modified files: emacs-wiki.el planner-rss.el planner.el 2004-03-07 15:49:23 GMT Sacha Chua patch-68 Summary: Add major-mode check for planner-rmail. Revision: emacs-wiki--sacha--1.0--patch-68 * planner-rmail.el (planner-rmail-annotation-from-mail): Add major-mode check. modified files: planner-rmail.el 2004-03-07 14:21:29 GMT Sacha Chua patch-66 Summary: Michal Maruska's idea: include #title in the wiki index. Revision: emacs-wiki--sacha--1.0--patch-66 * emacs-wiki.el: Merged in ideas from Michal Maruska's patch for including #title in the wiki index. See emacs-wiki-index-title-threshold for more details. (emacs-wiki-index-title-threshold): New variable. (emacs-wiki-get-title-fast): New defun. (emacs-wiki-file-alist-with-titles): New defun. (emacs-wiki-index-files-list): New convenience function. (emacs-wiki-index-file-title): New convenience function. (emacs-wiki-index-file-page): New convenience function. (emacs-wiki-generate-index): Observe emacs-wiki-index-title-threshold. (emacs-wiki-index): More verbose, now that it takes time to process. (emacs-wiki-publish-index): More verbose, now that it takes time to process. * planner-experimental.el (planner-generate-index): Observe emacs-wiki-index-title-threshold. modified files: emacs-wiki.el planner-experimental.el 2004-03-07 12:59:30 GMT Sacha Chua patch-65 Summary: Preliminary support for planner pages for BBDB records Revision: emacs-wiki--sacha--1.0--patch-65 * planner-bbdb.el (planner-bbdb-plan-field): New. (planner-bbdb-annotation-from-bbdb): Preliminary support for planner pages for BBDB records. modified files: planner-bbdb.el 2004-03-06 16:15:35 GMT Sacha Chua patch-64 Summary: Correctly make links even when page does not match emacs-wiki-name-regexp Revision: emacs-wiki--sacha--1.0--patch-64 * emacs-wiki.el (emacs-wiki-make-link): Correct regexp for forcing entire link to match emacs-wiki-name-regexp. * planner.el (planner-make-link): Removed compatibility function; left this as a defalias. (planner-annotation-from-planner-note): Used emacs-wiki-make-link instead. (planner-format-task): Used emacs-wiki-make-link instead. Properly dealt with links that did not match the name regular expression. (planner-copy-or-move-task): Used emacs-wiki-make-link instead. (planner-update-task): Used emacs-wiki-make-link instead. modified files: emacs-wiki.el planner.el 2004-03-06 08:44:36 GMT Sacha Chua patch-62 Summary: Added planner-vm. Minor bugfixes in other modules. Revision: emacs-wiki--sacha--1.0--patch-62 * planner-vm.el: New file. new files: .arch-ids/planner-vm.el.id planner-vm.el modified files: emacs-wiki.el planner-rmail.el 2004-03-06 05:17:12 GMT Sacha Chua patch-60 Summary: Promote planner-default-task-priority to a customizable variable. Revision: emacs-wiki--sacha--1.0--patch-60 * planner.el (planner-default-task-priority): Promote to a customizable variable. modified files: planner.el 2004-03-05 16:54:50 GMT Sacha Chua patch-59 Summary: planner-renumber-tasks renumbers chunks of tasks Revision: emacs-wiki--sacha--1.0--patch-59 * planner.el (planner-renumber-tasks): Renumber chunks of tasks, not only the first one. This lets you have a Completed Tasks section, although you still have to manually move tasks over to it. Maybe we can have a hook to control this, if other people find "Completed Tasks" interesting. modified files: planner.el 2004-03-03 15:47:22 GMT Sacha Chua patch-57 Summary: planner-rmail added, common mail functions moved into planner.el or planner-bbdb.el, redundant defun removed Revision: emacs-wiki--sacha--1.0--patch-57 * planner.el (planner-get-name-from-address): New defun. * planner-rmail.el: New file. * planner-gnus.el (planner-gnus-get-name-from-address): Moved to planner-bbdb as there was nothing Gnus-specific about this function. (planner-gnus-annotation-from-summary): Use planner-ignored-from-addresses from planner instead of gnus-ignored-from-addresses. Use planner-get-name-from-address (defined in planner, redefined in planner-bbdb) instead of planner-gnus-get-name-from-address. (planner-gnus-annotation-from-message): Use planner-ignored-from-addresses from planner instead of gnus-ignored-from-addresses. Use planner-get-name-from-address (defined in planner, redefined in planner-bbdb) instead of planner-gnus-get-name-from-address. * planner-bbdb.el (planner-bbdb-get-name-from-address): New defun. Alternative for planner-get-name-from-address. (planner-get-name-from-address): Set to planner-bbdb-get-name-from-address when planner-bbdb is loaded. * planner.el (planner-annotation-functions): Removed planner-annotation-from-planner-note from default value until it is fully supported again. (planner-make-planner-link): Check if emacs-wiki-name-regexp completely matches wiki-link. * planner.el: Rearranged compatibility functions (planner-ignored-from-addresses): New option. (planner-make-planner-link): Removed. planner-make-link is sufficient. (planner-copy-or-move-task): Use planner-make-link. (planner-update-task): Use planner-make-link. * emacs-wiki.el (emacs-wiki-make-link): Check if emacs-wiki-name-regexp completely matches wiki-link. new files: .arch-ids/planner-rmail.el.id planner-rmail.el modified files: emacs-wiki.el planner-bbdb.el planner-gnus.el planner.el 2004-03-02 04:14:04 GMT Sacha Chua patch-56 Summary: Fixed embarrassing typo in compatibility function planner-link-unescape Revision: emacs-wiki--sacha--1.0--patch-56 * planner.el (fboundp): Whoops, planner-link-unescape was typo'd to planner-link-escape. Thanks to Nascif Abousalh-Neto for the bug report! modified files: planner.el 2004-03-01 06:17:51 GMT Sacha Chua patch-55 Summary: Bugfix in planner-escape-link and planner-unescape-link. Revision: emacs-wiki--sacha--1.0--patch-55 * planner.el (planner-escape-link): Whoops, forgot to return text. (planner-unescape-link): Whoops, forgot to return text. modified files: planner.el 2004-03-01 05:01:21 GMT Sacha Chua patch-54 Summary: Load the correct library for grep-command. Revision: emacs-wiki--sacha--1.0--patch-54 * planner-id.el (require): Load the correct library for grep-command. This is 'compile for XEmacs and stable Emacs 21, but 'grep for Emacs 21 CVS. modified files: planner-id.el 2004-02-29 15:00:03 GMT Sacha Chua patch-53 Summary: Misc. documentation fixes Revision: emacs-wiki--sacha--1.0--patch-53 Whoops, wrong boilerplate text on many of the files. Misc. whitespace fixes as well. modified files: planner-bbdb.el planner-diary.el planner-experimental.el planner-gnus.el planner-id.el planner-notes.el planner-rss.el planner-schedule.el planner-timeclock.el planner-w3m.el planner.el remember-bbdb.el remember-bibl.el remember-experimental.el remember-planner.el remember.el 2004-02-29 14:44:33 GMT Sacha Chua patch-52 Summary: Added compatibility functions for older versions of emacs-wiki.el. Revision: emacs-wiki--sacha--1.0--patch-52 * planner.el (fboundp): Added compatibility functions planner-link-escape, planner-link-unescape, planner-make-link, and advice around emacs-wiki-wiki-link-target. * planner-gnus.el (planner-gnus-annotation-from-summary): Used compatibility functions. (planner-gnus-annotation-from-message): Used compatibility functions. modified files: planner-gnus.el planner.el 2004-02-27 06:11:47 GMT Sacha Chua patch-51 Summary: Better XEmacs compatibility Revision: emacs-wiki--sacha--1.0--patch-51 Not only do all the files now pass develock, but most of the XEmacs compile errors are gone. WHEW! modified files: emacs-wiki.el planner-bbdb.el planner-diary.el planner-experimental.el planner-gnus.el planner-id.el planner-notes.el planner-rss.el planner-schedule.el planner-timeclock.el planner-w3m.el planner.el remember-experimental.el remember-planner.el remember.el 2004-02-27 00:06:35 GMT Daniel Neri patch-2 Summary: fix a couple of typos Revision: emacs-wiki--planner--0--patch-2 modified files: planner.el remember-planner.el 2004-02-26 23:59:37 GMT Daniel Neri patch-1 Summary: sync commentary with reality Revision: emacs-wiki--planner--0--patch-1 modified files: planner-gnus.el 2004-02-26 12:02:20 GMT Sacha Chua patch-49 Summary: Rearranged customization options and removed Gnus links from published pages Revision: emacs-wiki--sacha--1.0--patch-49 * planner.el: Rearranged customization entries for ease of use. (planner-mode-hook): Removed from customization entries as this is automatically defined by the creation of a major mode. (planner-markup-url): Do not strip other characters from the ID. * planner-gnus.el (planner-gnus-resolve-url): Gnus IDs should not be displayed. (planner-resolve-url-table): Add planner-gnus-resolve-url here. modified files: planner-gnus.el planner.el 2004-02-23 17:32:30 GMT Sacha Chua patch-48 Summary: Bugfix: planner-id.el should call planner-highlight-region Revision: emacs-wiki--sacha--1.0--patch-48 * planner-id.el (planner-id-markup): Use planner-highlight-region instead of planner-markup-region. modified files: planner-id.el 2004-02-23 17:25:49 GMT Sacha Chua patch-47 Summary: Bugfix: planner-bbdb-resolve-url Revision: emacs-wiki--sacha--1.0--patch-47 * planner-bbdb.el (planner-resolve-url-table): Use planner-bbdb-resolve-url. (planner-bbdb-resolve-url): Renamed from planner-bbdb-markup-url. modified files: planner-bbdb.el 2004-02-23 11:52:48 GMT Sacha Chua patch-46 Summary: Highlight functions should be named -highlight-, not -markup-. Tasks marked up specially. Minor bugfixes. Revision: emacs-wiki--sacha--1.0--patch-46 * planner.el (planner-resolve-url-google): Renamed from planner-markup-url-google. (planner-resolve-url-table): Renamed from planner-markup-url-table (planner-markup-url): Use planner-resolve-url-table (planner-mode): Highlight functions are now named -highlight- instead of -markup-. (planner-highlight-region): Renamed from planner-markup-region. (planner-highlight-tasks): Renamed from planner-markup-tasks. Use planner-highlight-region. (planner-highlight-notes): Renamed from planner-markup-notes. (planner-markup-url): Remove protocol - is not a parameter. (planner-publishing-markup): Mark up tasks specially. (planner-markup-task): New function. modified files: planner.el 2004-02-23 10:36:38 GMT Sacha Chua patch-45 Summary: Make planner-url a list of regular expressions Revision: emacs-wiki--sacha--1.0--patch-45 * planner.el (planner-url-list): Now a list of regular expressions instead of strings. modified files: planner.el 2004-02-22 16:41:57 GMT Sacha Chua patch-44 Summary: Major change: split planner.el and remember.el into modules Revision: emacs-wiki--sacha--1.0--patch-44 * planner.el: Split off -bbdb, -gnus, -schedule, -timeclock and -w3m. Compiles cleanly under Emacs 21 CVS. (planner-url-list): New variable for better modularization. (planner-update-wiki-project): Automatically compose regular expression for emacs-wiki-url-regexp. (planner-markup-url-table): New variable. (planner-browse-url-functions): New variable. * remember.el: Split off -bbdb, -bibl and -planner. Compiles cleanly under Emacs 21 CVS. new files: .arch-ids/planner-bbdb.el.id .arch-ids/planner-gnus.el.id .arch-ids/planner-schedule.el.id .arch-ids/planner-timeclock.el.id .arch-ids/planner-w3m.el.id .arch-ids/remember-bbdb.el.id .arch-ids/remember-bibl.el.id .arch-ids/remember-planner.el.id planner-bbdb.el planner-gnus.el planner-schedule.el planner-timeclock.el planner-w3m.el remember-bbdb.el remember-bibl.el remember-planner.el modified files: planner-experimental.el planner-id.el planner-notes.el planner.el remember-experimental.el remember.el 2004-02-19 11:01:05 GMT Sacha Chua patch-42 Summary: Added categorized feeds to planner-rss.el Revision: emacs-wiki--sacha--1.0--patch-42 * planner-rss.el (planner-rss-file-name): Changed documentation string. (planner-rss-category-feeds): New variable. Customize this to get categorized feeds. (planner-rss-add-note): Perform regular-expression matching on the original text and copy matched entries to category feeds. * planner.el (planner-note-title): New defun. (planner-note-timestamp): New defun. (planner-note-body): New defun. (planner-narrow-to-note): Save excursion. modified files: planner-rss.el planner.el 2004-02-18 03:31:36 GMT Sacha Chua patch-41 Summary: Embarrassing typo in planner.el Revision: emacs-wiki--sacha--1.0--patch-41 * planner.el (planner-list-unfinished-tasks): Whoops! Added an n by mistake. Thanks to Frederik Fouvry for pointing this out. modified files: planner.el 2004-02-17 04:23:28 GMT Sacha Chua patch-39 Summary: Bugfix in planner-name-regexp Revision: emacs-wiki--sacha--1.0--patch-39 * planner.el (planner-name-regexp): Corrected regular expression so that emacs-wiki recognizes yyyy.mm.dd#link again. modified files: planner.el 2004-02-17 03:09:30 GMT Sacha Chua patch-38 Summary: Added info URLs to planner.el Revision: emacs-wiki--sacha--1.0--patch-38 * planner.el (planner-url-regexp): Added info handling. (planner-browse-url): Added info handling. Thanks to Frederik Fouvry for patch. modified files: planner.el planner2diary.py 2004-02-17 02:54:53 GMT Sacha Chua patch-36 Summary: Fixed emacs-wiki matching by removing grouping from planner-name-regexp. Revision: emacs-wiki--sacha--1.0--patch-36 * planner.el (planner-name-regexp): Removed grouping construct as this threw off emacs-wiki matching. modified files: planner.el 2004-02-15 13:49:52 GMT Sacha Chua patch-35 Summary: More planner-rss fixes to deal with read-only text. Revision: emacs-wiki--sacha--1.0--patch-35 * planner.el (planner-current-note-info): Removed text properties from body. * planner-rss.el (planner-rss-add-note): Removed planner-note-info-from-string reference. Used planner-current-note-info from planner.el instead. Used planner-current-note-info to get the body. Properly removes overlays and text-properties from read-only text. modified files: planner-rss.el planner.el 2004-02-15 06:32:20 GMT Sacha Chua patch-34 Summary: Prepared planner-rss.el for first release. Revision: emacs-wiki--sacha--1.0--patch-34 * planner-rss.el: Renamed from rss.el. Added commentary. Changed function prefix. (planner-rss-initial-contents): Merged other one-time variables into this. Moved to planner customize group. (planner-rss-base-url): Moved to planner customize group. (planner-rss-file-name): Moved to planner customize group. (planner-rss-initialize): Used planner-rss-initial-contents. modified files: planner-rss.el renamed files: .arch-ids/rss.el.id ==> .arch-ids/planner-rss.el.id rss.el ==> planner-rss.el 2004-02-14 15:09:36 GMT Sacha Chua patch-33 Summary: Added rss.el Revision: emacs-wiki--sacha--1.0--patch-33 You need rss.el for the blogging to RSS stuff. new files: .arch-ids/rss.el.id rss.el 2004-02-14 14:44:10 GMT Sacha Chua patch-32 Summary: Removed redundant code from planner-experimental.el Revision: emacs-wiki--sacha--1.0--patch-32 * planner-experimental.el (planner-note-timestamp-regexp): Deleted. (planner-analyze-headline): Deleted. (planner-list-headlines): Deleted. (planner-search-notes): Moved into planner.el. (planner-search-notes-internal): Moved into planner.el. * planner.el (planner-search-notes-internal): Moved from planner-experimental.el (planner-current-note-info): Moved actual timestamp regexp into code. modified files: planner-experimental.el planner.el 2004-02-14 09:50:58 GMT Sacha Chua patch-30 Summary: Bugfix: planner-name-regexp had invalid regular expression syntax. Revision: emacs-wiki--sacha--1.0--patch-30 * planner.el (planner-name-regexp): Fix embarrassing regular expression bug. modified files: planner.el 2004-02-13 03:42:46 GMT Sacha Chua patch-29 Summary: Documentation fix for local planner task references Revision: emacs-wiki--sacha--1.0--patch-29 * planner.el: Removed incorrect documentation note about local planner task references. (planner-name-regexp): Shorter regular expression. modified files: planner.el 2004-02-11 14:58:53 GMT Sacha Chua patch-28 Summary: Bugfix: planner-seek-to-first inserts correct number of spaces. Revision: emacs-wiki--sacha--1.0--patch-28 * planner.el (planner-seek-to-first): Function now attempts to insert the correct number of spaces. This may be slower, though, with all the regular-expression matching. It now correctly deals with sections at the bottom end of a file and sections placed right before sections (< 2 blank lines in between). modified files: planner.el 2004-02-11 09:48:30 GMT Sacha Chua patch-27 Summary: Bugfixes in planner-seek-to-function that affected all those with planner-seek-create-at-bottom Revision: emacs-wiki--sacha--1.0--patch-27 * planner.el (planner-seek-to-first): Try to seek to the section first. Call planner-seek-section-function only if it is not found. (planner-seek-create-at-top): Moved the seek to planner-seek-to-first. This function now only creates a new section. (planner-seek-create-at-bottom): Moved the seek to planner-seek-to-first. This function now only creates a new section. modified files: planner.el 2004-02-09 03:10:08 GMT Sacha Chua patch-26 Summary: Doc tweaks Revision: emacs-wiki--sacha--1.0--patch-26 * planner.el: Tweaked allout configuration so that commentary is always displayed. modified files: planner.el 2004-02-09 02:44:50 GMT Sacha Chua patch-24 Summary: Added major-mode check to emacs-wiki Revision: emacs-wiki--sacha--1.0--patch-24 * planner.el (planner-annotation-from-wiki): Added derived-mode-p check for emacs-wiki-mode. (planner-annotation-from-planner): Added derived-mode-p check for planner-mode. (planner-annotation-from-planner-note): Added derived-mode-p check for planner-mode. modified files: planner.el 2004-02-06 04:11:56 GMT Sacha Chua patch-23 Summary: Minor bugfixes with replace-regexp-in-string and the message-id regexp. Revision: emacs-wiki--sacha--1.0--patch-23 * planner.el (planner-strip-whitespace): To be safe, use the replace-regexp-in-string defined in xemacs. (planner-gnus-get-message-id): To be safe, use the replace-regexp-in-string defined in xemacs. (planner-gnus-get-message-id): Fix embarrassing regexp error. modified files: planner.el 2004-02-05 10:44:06 GMT Sacha Chua patch-22 Summary: Minor bugfixes Revision: emacs-wiki--sacha--1.0--patch-22 * planner.el (planner-task-format): Returned old behavior of justifying priority properly. (planner-markup-tasks): Deal with different kinds of spaces. (planner-gnus-get-message-id): More flexible matching. modified files: planner.el 2004-02-01 05:37:06 GMT Sacha Chua patch-21 Summary: Added URL escaping to emacs-wiki Revision: emacs-wiki--sacha--1.0--patch-21 emacs-wiki-wiki-link-target unescapes the wiki link. planner-gnus-get-message-id deals with summary mode. planner-annotation-from-gnus uses emacs-wiki-make-link. planner-annotation-from-gnus-summary uses emacs-wiki-make-link. New functions: emacs-wiki-link-escape emacs-wiki-link-unescape emacs-wiki-make-link modified files: emacs-wiki.el planner.el 2004-01-28 06:56:15 GMT Sacha Chua patch-20 Summary: planner-default-task-priority Revision: emacs-wiki--sacha--1.0--patch-20 Ken Rachynski asked for a way to set the default task priority. Here it is - planner-default-task-priority (new variable, controls planner-create-task). modified files: planner.el 2004-01-28 06:52:08 GMT Sacha Chua patch-19 Summary: Font-locking more correct Revision: emacs-wiki--sacha--1.0--patch-19 Status font-locking now extends to beginning of line. modified files: planner.el 2004-01-28 06:43:16 GMT Sacha Chua patch-18 Summary: Improved font-locking Revision: emacs-wiki--sacha--1.0--patch-18 New variable: planner-hide-task-status-when-highlighting Martin Morgan suggested highlighting only a small part of the task, as wide seas of red can be quite overwhelming. Tried it out and thought it was a cool idea, so this version highlights only the category/priority with the category color and now properly does the completed/in-progress/delegated task highlighting. Martin sent a patch, too, which made the status invisible, but I like seeing the status so that I can change it by hand. New variable planner-hide-task-status-when-highlighting controls this. modified files: planner.el 2004-01-27 01:15:48 GMT Sacha Chua patch-17 Summary: Added fboundp check for remove-overlays Revision: emacs-wiki--sacha--1.0--patch-17 Apparently, older Emacsen don't have the remove-overlays function. Added fboundp check. Strange - if there's an overlay, how does one propose to remove all of them anyway? Anyway, planner-markup-region should do the right thing now. modified files: planner.el 2004-01-25 05:31:00 GMT Sacha Chua patch-15 Summary: planner-tasks-tag Revision: emacs-wiki--sacha--1.0--patch-15 is a new emacs-wiki tag. When published to HTML, this is replaced by a list of all the tasks. You can control the status by specifying a regular expression to match. For example, will list all completed tasks, while will list all incomplete tasks. This is handled by the planner-task--tag function. is part of the planner-markup-tags list. planner-list-tasks-with-status now takes a regular expression for STATUS. planner-list-unfinished-tasks uses the modified planner-list-tasks-with-status. modified files: planner.el 2004-01-25 04:23:14 GMT Sacha Chua patch-14 Summary: planner-list-tasks-with-status Revision: emacs-wiki--sacha--1.0--patch-14 planner-list-tasks-with-status is a new function that generalizes planner-list-unfinished-tasks. If you invoke it with a prefix argument, the sense is inverted. planner-list-unfinished-tasks now calls planner-list-tasks-with-status. modified files: planner.el 2004-01-25 04:03:17 GMT Sacha Chua patch-13 Summary: Tasks are colored according to their category Revision: emacs-wiki--sacha--1.0--patch-13 Ephrem Christopher Walborn suggested making planner-markup-tasks color A tasks red, B tasks blue, and C tasks green. This patch colors it as suggested. New function planner-markup-region chooses between overlays and text properties, using overlays whenever possible. Seems to work, and allows me to easily combine different attributes. planner-id.el now uses the new planner-markup-region. Also, planner-id.el is now UNIX-encoded. modified files: planner-id.el planner.el 2004-01-25 03:14:57 GMT Sacha Chua patch-12 Summary: Merged David Smith's patch for planner-copy-or-move-task, planner-mark-task, and planner-read-date Revision: emacs-wiki--sacha--1.0--patch-12 planner-copy-or-move-task's invocation of planner-format-task had left-over code from when planner inserted the string itself instead of using planner-format-task. Not only that, the condition was incorrect. I'd tried to use it to retain non-plan-page annotations, but that should have been after the plan-page entry. Now that we're using planner-format-task, I can just use a when form that'll evaluate to nil. Strangely, however, M-x plan has been working without ill effects. planner-mark-task wasn't marking it with the specified task status. Silly me. planner-read-date now does save-excursion and save-window-excursion. modified files: planner.el 2004-01-24 19:47:53 GMT David D. Smith patch-11 Summary: create proper links to planner pages Revision: emacs-wiki--dds--1.0--patch-11 Better implementation of what I tried to do in patch-8. modified files: planner.el 2004-01-24 19:46:31 GMT David D. Smith patch-10 Summary: revert patch-8: create proper links to planner pages Revision: emacs-wiki--dds--1.0--patch-10 This patch was not correct. Revert to old version for now. modified files: planner.el 2004-01-24 16:01:04 GMT David D. Smith patch-9 Summary: save-excursion in planner-read-date Revision: emacs-wiki--dds--1.0--patch-9 A save-excursion is necessary in planner-read-date because save-window-excursion does not save the location of point in buffer; it saves which window is active. The location of point in buffer is necessary when planner-copy-or-move-task calls planner-current-task-info; the symptom is that planner-copy-or-move-task operates on the first task in the buffer, not the task that point was on when the operation started. modified files: planner.el 2004-01-24 15:54:46 GMT David D. Smith patch-8 Summary: create proper links to planner pages Revision: emacs-wiki--dds--1.0--patch-8 In planner-copy-or-move-task, when updating the new date page, the way attempted to make a link to wherever the task in question was previously linked to. This works ok for new tasks but is not the proper behavior for *rescheduling* tasks. So, instead, just make a link to the planner page that this task belongs to. modified files: planner.el 2004-01-24 15:44:15 GMT David D. Smith patch-7 Summary: planner-mark-task set mark, not "X" Revision: emacs-wiki--dds--1.0--patch-7 Oops, planer-mark-task was just setting all marks to "X", not to the mark parameter that is passed into the function. modified files: planner.el 2004-01-24 04:54:44 GMT Sacha Chua patch-11 Summary: Made planner.el output XHTML-compliant Revision: emacs-wiki--sacha--1.0--patch-11 Applied Ephrem Christopher Walborn's patch to make planner.el's output more XHTML-compliant by using instead of . modified files: planner.el 2004-01-23 08:45:29 GMT Sacha Chua patch-10 Summary: planner-list-unfinished-tasks lists all non-X Revision: emacs-wiki--sacha--1.0--patch-10 Instead of just listing the undone tasks (_), planner-list-unfinished-tasks lists all incomplete tasks (non-X status). That way, in-progress and delegated tasks will be included in the list. modified files: planner.el 2004-01-22 09:10:21 GMT Sacha Chua patch-9 Summary: task extraction Revision: emacs-wiki--sacha--1.0--patch-9 - New user function: M-x planner-list-unfinished-tasks displays all the unfinished tasks. - New defun: planner-extract-tasks-with-status. - New defun: planner-extract-tasks. - Rearranged many of the functions. - Passes checkdoc again. modified files: planner.el 2004-01-21 01:16:33 GMT Sacha Chua patch-8 Summary: Save planner-read-date's map Revision: emacs-wiki--sacha--1.0--patch-8 Modified davidsmith's patch to restore the old map, whatever it is. modified files: planner.el 2004-01-21 01:07:56 GMT Sacha Chua patch-7 Summary: Work with local-write-file-hooks Revision: emacs-wiki--sacha--1.0--patch-7 Older Emacsen don't have the functions I used before. modified files: planner-id.el 2004-01-20 08:47:20 GMT Sacha Chua patch-5 Summary: Revision: emacs-wiki--sacha--1.0--patch-5 Moved note functions from planner-experimental.el to planner.el. Fixed planner-mark-task bug in planner.el. Thanks to Brent Goodrick for bug report. modified files: planner-experimental.el planner.el 2004-01-20 01:00:15 GMT David D. Smith patch-2 Summary: whitespace adjustment Revision: emacs-wiki--dds--1.0--patch-2 Use same indent settings as Sacha. modified files: planner.el 2004-01-20 00:18:45 GMT David D. Smith patch-1 Summary: unwind-protect for planner-read-date Revision: emacs-wiki--dds--1.0--patch-1 planner-read-date() changes the local key map, so use an unwind-protect construct to clean up. modified files: planner.el 2004-01-11 13:02:56 GMT Sacha Chua patch-4 Summary: Revision: emacs-wiki--sacha--1.0--patch-4 Made planner-create-task-from-buffer the default instead of planner-create-task. modified files: planner.el 2004-01-09 01:26:58 GMT Sacha Chua patch-2 Summary: Revision: emacs-wiki--sacha--1.0--patch-2 Added an interactive planner-index. modified files: planner-experimental.el 2004-01-01 06:32:29 GMT Sacha Chua patch-1 Summary: Grand import Revision: emacs-wiki--sacha--1.0--patch-1 Junked my old archive as couldn't figure out how to rename it neatly, so we're back to the old patchlevels. new files: .arch-ids/planner-diary.el.id .arch-ids/planner-experimental.el.id .arch-ids/planner-id.el.id .arch-ids/planner-notes.el.id .arch-ids/planner.el.id .arch-ids/planner2diary.py.id .arch-ids/remember-experimental.el.id .arch-ids/remember.el.id planner-diary.el planner-experimental.el planner-id.el planner-notes.el planner.el planner2diary.py remember-experimental.el remember.el modified files: emacs-wiki.el ;; Local Variables: ;; coding: utf-8 ;; End: planner-el/ChangeLog.2000066400000000000000000007416031226462314700150470ustar00rootroot000000000000002005-12-31 00:34:19 GMT Michael Olson patch-143 Summary: planner-publish: Make and work. Revision: planner-muse--mwolson--1.0--patch-143 * planner-publish.el (planner-publish-markup-tags): Add past-notes tag. (planner-publish-notes-tag): Use a new version from Dale Smith. (planner-past-notes-tag): Try to port this, since it is part of Planner. * planner.el (planner-notes-tag): Remove. (planner-past-notes-tag): Move to planner-publish.el. modified files: ChangeLog planner-publish.el planner.el 2005-12-26 07:35:46 GMT Michael Olson patch-142 Summary: planner-accomplishments: Get rid of extra underlined part. Revision: planner-muse--mwolson--1.0--patch-142 * planner-accomplishments.el (planner-accomplishments-format-table): Don't put spaces inside of the link. Thanks to Paul Lussier for the report. modified files: ChangeLog planner-accomplishments.el 2005-12-26 05:38:13 GMT Michael Olson patch-141 Summary: Fix bug with finding anchors. Revision: planner-muse--mwolson--1.0--patch-141 * planner.el (planner-visit-link, planner-visit-link): Apply patch from Sacha that fixes an anchor-searching bug. modified files: ChangeLog planner.el 2005-12-25 01:57:55 GMT Michael Olson patch-140 Summary: Remove planner-regexp-space. Revision: planner-muse--mwolson--1.0--patch-140 * planner.el (planner-regexp-space): Remove, since it isn't used. modified files: ChangeLog planner.el 2005-12-23 22:44:43 GMT Michael Olson patch-139 Summary: Massively update documentation for the Muse transition. Revision: planner-muse--mwolson--1.0--patch-139 * Makefile (upload): Change location where we upload releases. * debian/control (Description): s/emacs-wiki/Emacs Muse/. * planner-calendar.el: Attempt to port this to Muse. * planner-cyclic.el, planner-erc.el, planner-rss.el: Remove ChangeLog link. * planner-el.texi: Replace all mentions of emacs-wiki with Muse. Try to adapt some instructions for Muse. More work is needed, especially in the installation section. Remove a lot of extra whitespace and fill overlong lines. Add myself to the history section. Remove Sacha's config, since I'd rather just include config files in an examples directory, like with Muse -- it gets tedious to maintain, too. * planner-multi.el (planner-multi-separator): s/emacs-wiki/muse/. * planner-notes-index.el: Remove extra URL for emacs-wiki. * planner-rdf.el: Update documentation. (planner-rdf-publish-file): Match against muse-image-regexp. * planner.el: Update documentation. modified files: ChangeLog Makefile debian/control planner-calendar.el planner-cyclic.el planner-el.texi planner-erc.el planner-multi.el planner-notes-index.el planner-rdf.el planner-rss.el planner.el 2005-12-19 21:38:28 GMT Michael Olson patch-137 Summary: planner-publish: Fix publishing bug. Revision: planner-muse--mwolson--1.0--patch-137 * planner-publish.el (planner-insert-markup): Fix bug. Thanks to Jim Ottaway and Seth Falcon for the fix. modified files: ChangeLog planner-publish.el 2005-12-18 09:35:47 GMT Jim Ottaway patch-34 Summary: planner-appt: forthcoming appts changes Revision: planner--jeho--1.1--patch-34 * planner-appt.el (planner-appt-forthcoming-repeat-date-string): New option for the repeated date cell (planner-appt-forthcoming-look-at-cyclic-flag): Make this nil by default. (planner-appt-forthcoming-get-appts): Check that planner-cyclic is loaded. (planner-appt-forthcoming-format): Empty cell handling: if the cell contains some ink, make it a link. modified files: planner-appt.el 2005-12-17 18:09:25 GMT Jim Ottaway patch-33 Summary: planner-bibtex: peripatetic point cure Revision: planner--jeho--1.1--patch-33 * planner-bibtex.el (planner-bibtex-annotation-new, planner-bibtex-annotation-old): wrap in a save-excursion to stop point moving around. modified files: planner-bibtex.el 2005-12-17 16:38:31 GMT Jim Ottaway patch-31 Summary: planner-el.texi: small edits Revision: planner--jeho--1.1--patch-31 * planner-el.texi: Added a few @noindents in the planner-appt section to make examples within paragaphs look right. modified files: planner-el.texi 2005-12-17 13:11:32 GMT Jim Ottaway patch-30 Summary: planner-appt: small fix for forthcoming appts Revision: planner--jeho--1.1--patch-30 * planner-appt.el (planner-appt-task-schedule-item-p): New function. (planner-appt-update-appt-section,planner-appt-add-appts-from-schedule): Use the new function planner-appt-task-schedule-item-p. (planner-appt-forthcoming-get-appts): Check that a schedule item was not added from the task list. modified files: planner-appt.el 2005-12-17 12:50:23 GMT Jim Ottaway patch-29 Summary: planner-appt: improved empty cells; rename commands Revision: planner--jeho--1.1--patch-29 * planner-appt.el (planner-appt-format-appt-section-line): Remove the "''''" hack: it doesn't appear to be necessary any more. (planner-appt-forthcoming-format): Change the repeated date cell format to " - " [to save precious ink]. (planner-appt-forthcoming-display): Renamed from planner-appt-display-forthcoming for consistency. (planner-appt-forthcoming-update-section): Renamed from planner-appt-update-forthcoming-appts-section for consistency. (planner-appt-forthcoming-update-section-maybe): Renamed from planner-appt-update-forthcoming-appts-section-maybe for consistency * planner-el.texi: Changed renamed function names for planner-appt-forthcoming- commands. modified files: planner-appt.el planner-el.texi 2005-12-16 23:32:20 GMT Michael Olson patch-135 Summary: Fix tag coloring breakage. Revision: planner-muse--mwolson--1.0--patch-135 * planner.el (planner-setup-highlighting): Add color markup for dates to the bottom of the markup list, so that it doesn't break coloring of tags. modified files: ChangeLog planner.el 2005-12-16 21:20:11 GMT Michael Olson patch-134 Summary: schedule.el: Move to contrib directory. Revision: planner-muse--mwolson--1.0--patch-134 * contrib/schedule.el: Moved here from the base directory. Fixed URL. * planner-schedule.el: Note that schedule.el is in the contrib directory. modified files: ChangeLog contrib/schedule.el planner-schedule.el renamed files: .arch-ids/schedule.el.id ==> contrib/.arch-ids/schedule.el.id schedule.el ==> contrib/schedule.el 2005-12-16 19:46:09 GMT Michael Olson patch-132 Summary: Generate autoloads file automatically from Makefile rules. Revision: planner-muse--mwolson--1.0--patch-132 * Makefile (EL): Avoid warning by removing planner-autoloads.el from list. (all): Generate autoloads. (autoloads): Make planner-autoloads.el. (planner-autoloads.el): Call `planner-generate-autoloads' from scripts/planner-build.el with arguments representing the directories to use when searching for autoloads. (realclean distclean fullclean): Remove autoloads. * scripts/planner-build.el (planner-generate-autoloads): Generate autoloads for Planner. Deal with XEmacs and its quirky insistence on doing most of the work itself. Expand all command line args so that the right directories are searched. Hardcode planner-autoloads.el as the name of the generated autoloads file. Use my custom header and footer, if possible. * planner-auto.el: Remove this, since we're using an automated method now. removed files: .arch-ids/planner-auto.el.id planner-auto.el modified files: ChangeLog Makefile scripts/planner-build.el 2005-12-16 15:32:18 GMT Michael Olson patch-131 Summary: planner-xtla: Apply patch from Stefan Reichör. Revision: planner-muse--mwolson--1.0--patch-131 * planner-xtla.el (planner-xtla-log-edit-add-note): Apply patch from Stefan Reichör. This should write the note to planner-today rather than temp*.muse. modified files: ChangeLog planner-xtla.el 2005-12-16 13:17:58 GMT Jim Ottaway patch-28 Summary: planner-appt: forthcoming appts Revision: planner--jeho--1.1--patch-28 * planner-appt.el: Added the forthcoming appointments code and shuffled everything around a bit. modified files: planner-appt.el 2005-12-16 12:54:43 GMT Jim Ottaway patch-27 Summary: planner-appt: remove documentation Revision: planner--jeho--1.1--patch-27 * planner-appt.el: Removed the documentation at the beginning of the file since it is in the texinfo file. modified files: planner-appt.el 2005-12-16 12:53:02 GMT Jim Ottaway patch-26 Summary: planner-el.texi: revise documentation for planner-appt Revision: planner--jeho--1.1--patch-26 modified files: planner-el.texi 2005-12-16 01:28:14 GMT Jim Ottaway patch-25 Summary: planner-appt: add hook for planner-appt-update Revision: planner--jeho--1.1--patch-25 * planner-appt.el (planner-appt-update-hook): New hook. (planner-appt-update): Run hook after updating. modified files: planner-appt.el 2005-12-15 12:07:52 GMT Jim Ottaway patch-24 Summary: planner-appt Revision: planner--jeho--1.1--patch-24 * planner-appt.el (planner-appt-format-time-and-description): Renamed from the confusing planner-appt-format-time-description. modified files: ChangeLog planner-appt.el 2005-12-14 15:52:57 GMT Andrew J. Korty patch-13 Summary: fix Muse 3.02.02 compatibility for planner-authz-index-as-string Revision: planner-muse--main--1.0--patch-13 - use planner-insert-markup instead of muse-insert-markup in planner-authz-index-as-string (same changes as mwolson@gnu.org--2005/planner-muse--mwolson--1.0--patch-125 applied to new code) modified files: planner-authz.el 2005-12-14 11:24:57 GMT Jim Ottaway patch-23 Summary: planner-appt: schedule regexp and task formatting Revision: planner--jeho--1.1--patch-23 * planner-appt.el (planner-appt-schedule-basic-regexp): Added a ?' character to allow for the ''''' ' cell forcing hack. (planner-appt-format-time-description): New function: separates out the formatting of time and task from planner-appt-make-appt-element. (planner-appt-make-appt-element): Use the new function for the time and task formatting. modified files: planner-appt.el scripts/planner-build.el 2005-12-13 23:58:41 GMT Michael Olson patch-128 Summary: planner-timeclock-summary-proj: Make it work with muse-file-extension. Revision: planner-muse--mwolson--1.0--patch-128 * planner-timeclock-summary-proj.el (planner-timeclock-summary-proj-current): Use planner-page-name so that this works with muse-file-extension enabled. Thanks to Pascal Quesseveur for the report. modified files: ChangeLog planner-timeclock-summary-proj.el 2005-12-13 14:52:06 GMT Michael Olson patch-127 Summary: planner-publish: Make planner-insert-markup a function. Revision: planner-muse--mwolson--1.0--patch-127 * planner-publish.el (planner-insert-markup): Make this into a function rather than trying to alias it. (planner-publish-title-tag): Fix compiler warning. modified files: ChangeLog planner-publish.el 2005-12-13 14:09:20 GMT Jim Ottaway patch-22 Summary: planner-appt: make appt highlighting conditional Revision: planner--jeho--1.1--patch-22 * planner-appt.el (planner-appt-limit-highlighting-flag): New customizable variable. (planner-appt-task-highlight): check that the user wants to limit highlighting to tasks and schedule; if so, check that this is a task or schedule line. modified files: planner-appt.el 2005-12-13 13:48:52 GMT Jim Ottaway patch-21 Summary: planner-appt: rewrite task appt section code Revision: planner--jeho--1.1--patch-21 * planner-appt.el (planner-appt-update-appt-section): Use a simpler method: add a text property to indicate that a line is derived from the task list. (planner-appt-add-appts-from-schedule): Use the text property added by planner-appt-update-appt-section to determine that a line should not be parsed. modified files: planner-appt.el 2005-12-13 04:30:42 GMT Michael Olson patch-126 Summary: planner-publish: Fix void-function error when compiling. Revision: planner-muse--mwolson--1.0--patch-126 * planner-publish.el (planner-insert-markup): Wrap eval-and-compile around this since it's a defsubst. Thanks to Jim Ottaway for the patch. modified files: ChangeLog Makefile.defs debian/changelog planner-publish.el 2005-12-11 16:41:15 GMT Michael Olson patch-125 Summary: planner-authz: Fix an issue with the Muse 3.02.02 release. Revision: planner-muse--mwolson--1.0--patch-125 * planner-authz.el: Use planner-insert-markup instead of muse-insert-markup. This should fix an issue with Muse 3.02.02. Thanks to Gerd Flaig for the report. modified files: ChangeLog planner-authz.el 2005-12-11 06:32:56 GMT Michael Olson patch-124 Summary: planner-psvn: Apply patch from Seth Falcon. Revision: planner-muse--mwolson--1.0--patch-124 * planner-psvn.el (planner-psvn-log-edit-add-note): Apply patch from Seth Falcon. This should write the note to planner-today rather than *temp*.muse. modified files: ChangeLog planner-psvn.el 2005-12-10 18:47:54 GMT Andrew J. Korty patch-11 Summary: fix index generation Revision: planner-muse--main--1.0--patch-11 - when AS-LIST is non-nil, our markup prevents the unordered list markup regexp from matching, so do our own list markup modified files: planner-authz.el 2005-12-08 14:36:37 GMT Andrew J. Korty patch-10 Summary: fix authz.mas generation Revision: planner-muse--main--1.0--patch-10 - properly detect whether we're publishing WikiPlanner - use correct name of `muse-after-project-publish-hook' modified files: planner-authz.el 2005-12-07 14:28:17 GMT Andrew J. Korty patch-9 Summary: fix bug in regexp introduced in patch-7 Revision: planner-muse--main--1.0--patch-9 - need (?:...) around | expression modified files: planner-authz.el 2005-12-07 13:21:03 GMT Andrew J. Korty patch-8 Summary: allow markup of elements inside note details Revision: planner-muse--main--1.0--patch-8 - don't set the read-only property on note details -- was preventing markup of embedded links modified files: planner-publish.el 2005-12-07 13:16:13 GMT Andrew J. Korty patch-7 Summary: fix markup of all-day appointments Revision: planner-muse--main--1.0--patch-7 - treat " " as a valid beginning time for an appointment so that all-day appointments get marked up just as any other appointment modified files: planner-authz.el 2005-12-06 01:52:48 GMT Andrew J. Korty patch-6 Summary: fix bug when used with muse-wiki.el Revision: planner-muse--main--1.0--patch-6 - fix definition of planner-authz-link-regexp modified files: planner-authz.el 2005-12-05 16:07:58 GMT Andrew J. Korty patch-5 Summary: avoid errors due to bad links Revision: planner-muse--main--1.0--patch-5 - use planner-authz-project-default when a nonexistent project page is referenced modified files: planner-authz.el 2005-12-05 15:34:43 GMT Andrew J. Korty patch-4 Summary: fix diary markup Revision: planner-muse--main--1.0--patch-4 - if planner-authz-appt-alt is set, insert an "alt" attribute with its value - fix documentation for diary markup: users should customize sectionalize-markup-tagname, not planner-sections - protect "<&|" Mason constructs from table markup modified files: planner-authz.el 2005-12-01 18:50:12 GMT Michael Olson patch-122 Summary: planner-publish: Try again to fix link issue. Revision: planner-muse--mwolson--1.0--patch-122 * planner-publish.el (planner-publish-task-tag): Make another attempt at fixing the link issue. modified files: ChangeLog planner-publish.el 2005-11-30 22:44:12 GMT Jim Ottaway patch-15 Summary: planner-publish: fix task publishing Revision: planner--jeho--1.1--patch-15 * planner-publish.el (planner-html-markup-strings): Change planner-end-task so that it doesn't include the links, and has the correct [?] number of closing spans. (planner-publish-markup-task): Use planner-task-link-text for the links, so we get them all. (planner-publish-task-tag): Avoid making links readonly, so they can be handled by other publishing rules. Don't add links where there are none [don't add "()", that is]. modified files: ChangeLog planner-publish.el 2005-11-29 22:57:42 GMT Andrew J. Korty patch-1 Summary: Muse port and related improvements Revision: planner-muse--main--1.0--patch-1 - port to Muse - mark up planner's and tags instead of using markup regexps - should now be easier to support other templating systems than Mason by defining new styles and changing planner-authz-after-publish-hook - allow the regexp used to control access to sections to be customized (planner-authz-sections-regexp) - optionally control access to published diary entries (suggested by Jim Ottaway) - build per-page access control lists on demand instead of all at once at the beginning -- should be more efficient because we'll rarely need a full list - use :strings to avoid contortions when inserting Mason tags - instead of automatically generating an index, Muse seems to prefer that users add the index to pages using tags, so instead of overloading Muse's index-generating functions, simply provide planner-authz-index-as-string - while looping through planner-authz-pages-to-republish, actually pop off the entries to avoid republishing the same page twice if the process gets interrupted - run planner-authz-markup-sections on the whole buffer before planner.el gets a chance to convert everything into XML-like tags (I'd rather work with the
tags, but Muse needs support for nested tags of the same name) modified files: planner-authz.el 2005-11-29 18:00:48 GMT Michael Olson patch-117 Summary: planner-accomplishments: Fix muse-current-project issue. Revision: planner-muse--mwolson--1.0--patch-117 * planner-accomplishments.el (planner-accomplishments-show): Fix wrong-type-argument error by expanding planner-project before setting muse-current-project. Thanks to Seth Falcon for the report and suggested fix. modified files: ChangeLog planner-accomplishments.el 2005-11-27 20:32:24 GMT Jim Ottaway patch-14 Summary: planner-appt: fix formatting Revision: planner--jeho--1.1--patch-14 modified files: ChangeLog planner-appt.el 2005-11-27 03:31:54 GMT Michael Olson patch-116 Summary: planner-report: Implement suggestions from Seth Falcon. Revision: planner-muse--mwolson--1.0--patch-116 * planner-report.el (planner-report-generate): Add file extension to report file. (planner-report-pretty-print-plan-pages): New option that indicates whether the plan page names in reports should be pretty-printed. (planner-report-generate): Use the new option. modified files: ChangeLog planner-report.el 2005-11-25 14:06:18 GMT Jim Ottaway patch-13 Summary: planner-appt: fix infinite looping caused by planner-copy-or-move-region. Revision: planner--jeho--1.1--patch-13 * planner-appt.el (planner-appt-update-appt-section-maybe): Fix code indentation. (planner-copy-or-move-task): [function advice] Allow for new behaviour of planner-copy-or-move-region. modified files: planner-appt.el planner-multi.el 2005-11-24 10:52:27 GMT Jim Ottaway patch-12 Summary: planner.el: with-planner-update-setup Revision: planner--jeho--1.1--patch-12 * planner.el (with-planner-update-setup): Move this macro earlier in the file, ahead of its first use. modified files: ChangeLog planner.el 2005-11-23 06:30:45 GMT Michael Olson patch-114 Summary: planner-publish: Work with *both* muse--main and muse--rel. Revision: planner-muse--mwolson--1.0--patch-114 * planner-publish.el (planner-xml-extension): Rename from muse-xml-extension. (planner-xml-markup-strings): Rename from muse-xml-markup-strings. Make it belong to planner-publish customize group. (planner-insert-markup): Use a smarter construct that works on both muse--rel and muse--main. modified files: ChangeLog planner-publish.el 2005-11-23 06:21:01 GMT Michael Olson patch-113 Summary: planner-multi: Add option to put date links after other links. Revision: planner-muse--mwolson--1.0--patch-113 * planner-multi.el (planner-multi-date-links-last-p): New option that determines whether to put date links after links to other pages in the task description. The default is to put date links after other pages. (planner-multi-replan-task, planner-multi-create-task-from-info): Use this option. Thanks to Sacha for finding these places and to Paul Lussier for the suggestion. modified files: ChangeLog planner-multi.el 2005-11-23 06:08:47 GMT Michael Olson patch-112 Summary: planner-trunk: Use correct regexp and don't hardcode "Tasks" string. Revision: planner-muse--mwolson--1.0--patch-112 * planner-trunk.el: Apply patch from Sergey Vlasov. (planner-trunk-rule-list): Use correct syntax in regexp. (planner-trunk-tasks): Don't use the hardcoded "Tasks" string. modified files: ChangeLog planner-trunk.el 2005-11-23 03:00:04 GMT Michael Olson patch-111 Summary: planner-authz.el: Begin porting to Muse. Revision: planner-muse--mwolson--1.0--patch-111 * planner-authz.el: Begin porting this to Muse. It's only about halfway done. It's something to work on for vacation, I guess :^) . * test/planner-cyclic-test.el, test/planner-test.el: Rewrite for Muse. modified files: ChangeLog planner-authz.el test/planner-cyclic-test.el test/planner-test.el 2005-11-22 20:25:42 GMT Michael Olson patch-110 Summary: Make publishing work with Muse 3.02.02. Revision: planner-muse--mwolson--1.0--patch-110 * planner-publish.el: Replace "muse-insert-markup" with "planner-insert-markup". (planner-insert-markup): Compatibility function that makes publishing work with Muse 3.02.02. modified files: ChangeLog planner-publish.el 2005-11-22 20:19:40 GMT Michael Olson patch-108 Summary: planner-multi: Apply replan-task improvement from Seth Falcon. Revision: planner-muse--mwolson--1.0--patch-108 * planner-multi.el (planner-multi-replan-task): Apply patch from Seth Falcon. modified files: ChangeLog planner-multi.el 2005-11-22 16:38:48 GMT Michael Olson patch-107 Summary: Fix bug in planner-multi-create-task-from-info. Revision: planner-muse--mwolson--1.0--patch-107 * planner-multi.el (planner-multi-create-task-from-info): Fix bug introduced in recent changes. Thanks to Michael Heinrich for the heads up. modified files: ChangeLog planner-multi.el 2005-11-21 21:38:00 GMT Michael Olson patch-106 Summary: planner-appt: Try to fix infinite loop error. Revision: planner-muse--mwolson--1.0--patch-106 * planner-appt.el (planner-appt-de-wiki): Save place while we replace parts of the string. Hopefully this fixes an infinite loop error. modified files: ChangeLog planner-appt.el 2005-11-21 07:25:03 GMT Michael Olson patch-105 Summary: Fix obvious bug. Revision: planner-muse--mwolson--1.0--patch-105 * planner.el (planner-get-day-pages): Fix bug introduced in previous few patches. modified files: ChangeLog planner.el 2005-11-21 07:06:21 GMT Michael Olson patch-104 Summary: planner-multi: Don't create extraneous copy of new task. Revision: planner-muse--mwolson--1.0--patch-104 * planner-multi.el (planner-multi-create-task-from-info): Deal with case where planner-multi-copy-tasks-to-page is an extended link. Thanks to Seth Falcon for the report. modified files: ChangeLog planner-multi.el 2005-11-21 06:49:11 GMT Michael Olson patch-103 Summary: Make tasks overview, notes index, and a few other things work. Revision: planner-muse--mwolson--1.0--patch-103 * planner.el (planner-current-file): Defalias this to muse-current-file. (planner-list-daily-files, planner-get-day-pages): Return an alist rather than a date list. (planner-get-previous-existing-day, planner-get-next-existing-day) (planner-search-notes-internal, planner-past-notes-tag) (planner-index-as-string, plan): Adapt to deal with alist. (planner-extract-tasks): Deal with both alists and page lists. (planner-list-tasks-with-status): Implement handling of PAGES parameter as specified by the manual. * planner-tasks-overview.el (planner-tasks-overview-extract-all-tasks): Use the filename rather than the page name. Thanks to Janne Hellston and Seth Falcon for the heads up. * planner-notes-index.el (planner-notes-index-headlines-in-range): Deal with alist rather than page list. * planner-export-diary.el (planner-export-diary-get-schedule-entries): Ditto. * planner-appt.el (planner-appt-mark-calendar): Ditto. modified files: ChangeLog planner-appt.el planner-export-diary.el planner-notes-index.el planner-tasks-overview.el planner.el 2005-11-21 05:14:10 GMT Michael Olson patch-102 Summary: Fix parameters of planner-visit-link. Revision: planner-muse--mwolson--1.0--patch-102 * planner.el (planner-visit-link): Get rid of REFRESH-BUFFER parameter. Thanks to Seth Falcon for the heads up. modified files: ChangeLog planner.el 2005-11-21 05:07:07 GMT Michael Olson patch-101 Summary: Apply task ID patch from Sacha. Revision: planner-muse--mwolson--1.0--patch-101 Patch from Sacha: * planner-id.el (planner-id-get-id-from-string): Handle new KEY argument. (planner-id-find-task): Get ID in different ways depending on the task info. * planner-multi.el: Add defalias for planner-task-link-as-list. * planner.el (planner-task-link-as-list): New function that returns a list of all pages that the given task is on. modified files: ChangeLog planner-id.el planner-multi.el planner.el 2005-11-20 22:44:52 GMT Michael Olson patch-100 Summary: planner-multi: Attempt to keep multiple links from vanishing. Revision: planner-muse--mwolson--1.0--patch-100 * planner-multi.el (planner-multi-copy-or-move-task): Try to keep multiple links from vanishing. Thanks to Jim Ottaway for the patch. modified files: ChangeLog planner-multi.el 2005-11-19 23:41:50 GMT John Sullivan patch-1 Summary: Installed Sacha Chua's patch to fix the behavior of planner-cyclic at publishing time. Revision: planner-muse--johnsu01--1.0--patch-1 modified files: planner-cyclic.el 2005-11-18 23:51:18 GMT Michael Olson patch-98 Summary: This version of timeclock.el is only to be used with XEmacs. Revision: planner-muse--mwolson--1.0--patch-98 * contrib/timeclock.el: Give an error if we are using this with Emacs. This version is only meant to be used with XEmacs. (timeclock-propertize): Never call propertize. * planner-timeclock.el: Warn about this version of timeclock.el and Emacs. modified files: ChangeLog contrib/timeclock.el planner-timeclock.el 2005-11-17 05:08:58 GMT Michael Olson patch-97 Summary: Add contrib directory and XEmacs-friendly version of timeclock.el. Revision: planner-muse--mwolson--1.0--patch-97 * contrib: New directory containing small programs that are used with Planner, but are not part of it. * contrib/timeclock.el: Fixed version of timeclock.el that might work better with XEmacs. * planner-timeclock.el: Note that timeclock.el is now distributed with Planner in the contrib directory. new files: contrib/.arch-ids/=id contrib/.arch-ids/timeclock.el.id contrib/timeclock.el modified files: ChangeLog planner-timeclock.el planner.el new directories: contrib contrib/.arch-ids 2005-11-16 23:53:30 GMT Michael Olson patch-96 Summary: Make new Debian snapshot. Revision: planner-muse--mwolson--1.0--patch-96 modified files: ChangeLog Makefile.defs debian/changelog debian/rules 2005-11-08 11:40:30 GMT Jim Ottaway patch-10 Summary: planner-multi-task-xref: multiple date page fix Revision: planner--jeho--1.1--patch-10 * planner-multi.el (planner-multi-task-xref): Don't repeat the date page link. modified files: planner-multi.el 2005-11-08 11:31:16 GMT Jim Ottaway patch-9 Summary: planner-multi-task-delete-this-page: use planner-multi-replan-task Revision: planner--jeho--1.1--patch-9 * planner-multi.el (planner-multi-task-delete-this-page): A better solution than the previous patch: use planner-multi-replan-task with the appropriate arguments modified files: planner-multi.el 2005-11-08 11:13:53 GMT Jim Ottaway patch-8 Summary: planner-multi-task-delete-this-page Revision: planner--jeho--1.1--patch-8 * planner-multi.el (planner-multi-task-delete-this-page): Remove the page to delete from the link list correctly. Allow for various cases previously unaccommodated: two links becomes a single link, one link becomes no link at all. This also required allowing the regexp to match on a single link. modified files: planner-multi.el 2005-11-08 11:05:13 GMT Jim Ottaway patch-7 Summary: planner-multi: planner-make-link advice Revision: planner--jeho--1.1--patch-7 * planner-multi.el (planner-make-link): use planner-multi-make-link instead of muse-make-link modified files: planner-multi.el 2005-11-08 11:00:48 GMT Jim Ottaway patch-6 Summary: planner-multi-replan-task bugfix Revision: planner--jeho--1.1--patch-6 * planner-multi.el (planner-multi-replan-task): links weren't added to new pages modified files: planner-multi.el 2005-11-03 23:25:23 GMT Michael Olson patch-95 Summary: Publish raw dates as links. Revision: planner-muse--mwolson--1.0--patch-95 * planner-report.el: Fix commentary. * planner-publish.el (planner-publish-markup-regexps): Publish raw dates as links. modified files: ChangeLog planner-publish.el planner-report.el 2005-11-03 23:16:01 GMT Michael Olson patch-94 Summary: Turn raw dates into links. Revision: planner-muse--mwolson--1.0--patch-94 * planner.el (planner-date-regexp): Move higher. (planner-setup-highlighting): Make Muse handle implicit links matching dates. (planner-muse-handle-date-link): New function that defines how to recognize implicit date links. modified files: ChangeLog planner.el 2005-11-02 03:37:57 GMT Michael Olson patch-93 Summary: planner-timeclock-summary-proj.el: Add enhancements from twb. Revision: planner-muse--mwolson--1.0--patch-93 * planner-timeclock-summary-proj.el: Merge enhancements from Trent Buck. (planner-timeclock-summary-proj-header): New option that indicates the text to use for the planner timeclock summary section header. (planner-timeclock-summary-proj-section): Use a configurable header. Simplify. (planner-timeclock-proj-build-report): Make output a bit nicer. (planner-timeclock-proj-entries): Adjust match string. (planner-timeclock-summary-proj-insinuate): New function that causes the timeclock summary to be updated every time a Planner page is saved, if one exists on the current page. (planner-timeclock-proj-seconds-to-string): Rename from `planner-timeclock-summary-proj-seconds-to-weekdays-string'. modified files: ChangeLog planner-timeclock-summary-proj.el 2005-10-31 16:15:40 GMT Michael Olson patch-92 Summary: planner-deadline: Add "deadline-add" and "deadline-remove" functions. Revision: planner-muse--mwolson--1.0--patch-92 * planner-deadline.el (planner-deadline-change): Never remove a deadline here. (planner-deadline-add): New alias to planner-deadline-change. (planner-deadline-remove): New function that removes a deadline from the current task. modified files: ChangeLog planner-deadline.el 2005-10-31 15:54:03 GMT Michael Olson patch-91 Summary: planner: Make shortened dates like "2005.1.6" Just Work. Revision: planner-muse--mwolson--1.0--patch-91 * planner.el (planner-filename-to-calendar-date): Use match-string instead of substring to extract the days. This should allow shortened filenames like "2005.1.6" to Just Work. Thanks to Edgar Gonçalves for the report. modified files: ChangeLog planner.el 2005-10-30 18:51:48 GMT Michael Olson patch-90 Summary: planner-report: Port to Planner-Muse. Revision: planner-muse--mwolson--1.0--patch-90 * planner-report.el: Apply patch from Seth Falcon. (planner-report-generate): Use planner-date-regexp instead of planner-name-regexp. Use muse-wiki-publish-pretty-title, if defined, for link descriptions. (planner-report-find-notes): Use planner-link-base instead of emacs-wiki-wiki-base. (planner-report-find-tasks): Use nil 5th argument. modified files: ChangeLog planner-report.el 2005-10-29 19:56:40 GMT Michael Olson patch-89 Summary: Adapt to addition of muse-insert-markup in Muse. Revision: planner-muse--mwolson--1.0--patch-89 * planner-publish.el (planner-publish-section-tag) (planner-publish-title-tag, planner-publish-content-tag) (planner-publish-tasks-tag, planner-publish-task-tag) (planner-publish-notes-tag, planner-publish-note-tag): Adapt for recent addition of `muse-insert-markup' function to Muse. modified files: ChangeLog planner-publish.el 2005-10-29 08:53:18 GMT Michael Olson patch-88 Summary: Yet another anti-day-pages hack. Revision: planner-muse--mwolson--1.0--patch-88 * planner.el (planner-expand-name): Make it work with "30" as input and no day pages. modified files: ChangeLog planner.el 2005-10-29 08:31:20 GMT Michael Olson patch-87 Summary: anti-day-pages: Deal with hitting ENTER in planner-read-date. Revision: planner-muse--mwolson--1.0--patch-87 * planner.el (planner-expand-name): Missed one instance of planner-today. modified files: ChangeLog planner.el 2005-10-29 08:08:47 GMT Michael Olson patch-86 Summary: planner-deadline: Yet another anti-day-pages fix. Revision: planner-muse--mwolson--1.0--patch-86 * planner-deadline.el (planner-deadline-days-left): When we're not using day pages, do the right thing. modified files: ChangeLog planner-deadline.el 2005-10-29 07:53:25 GMT Michael Olson patch-85 Summary: Make day-page-less name expansion *really* work. Revision: planner-muse--mwolson--1.0--patch-85 * planner.el (planner-expand-name): Fix logic goof. modified files: ChangeLog planner.el 2005-10-29 07:39:14 GMT Michael Olson patch-84 Summary: Anti-day pages fix. Revision: planner-muse--mwolson--1.0--patch-84 * planner.el (planner-expand-name): If we're not using day pages, use the current date in various places. modified files: ChangeLog planner.el 2005-10-29 07:22:00 GMT Michael Olson patch-83 Summary: planner-deadline, planner-diary: Work even if day pages are disabled. Revision: planner-muse--mwolson--1.0--patch-83 * planner.el (planner-read-date): If new argument FORCE-READ is non-nil, prompt for the date even when we're not using day pages. The default behavior is not to prompt when day pages are not being used. * planner-deadline.el (planner-deadline-change): Ensure that we get a date, even if we're not using day pages. * planner-diary.el (planner-diary-add-entry): Ditto. modified files: ChangeLog planner-deadline.el planner-diary.el planner.el 2005-10-29 06:41:39 GMT Michael Olson patch-82 Summary: Minor debian packaging fix. Revision: planner-muse--mwolson--1.0--patch-82 * rules (binary-indep): Fix name of ChangeLog. modified files: ChangeLog debian/rules 2005-10-29 05:54:43 GMT Michael Olson patch-81 Summary: Tasks with deadlines will be moved properly from previous days. Revision: planner-muse--mwolson--1.0--patch-81 * planner-deadline.el: Whitespace munging. Make sure planner-deadline-update to planner-goto-hook -- it's a sure thing that this behavior will be desired if you have deadlines! (planner-deadline-change-hook): Add planner-deadline-update as the default value. * planner.el (planner-copy-or-move-region): Optimize. Only move upwards if no tasks exists at this line, or if we encounter an error. This should prevent planner from playing Russian Roulette with tasks from previous days, such as deadlines. (plan): Use point-min and point-max for the sake of clarity. modified files: ChangeLog planner-deadline.el planner.el 2005-10-29 00:32:45 GMT Michael Olson patch-80 Summary: planner-bibtex: Use "bibtex:" to match bibtex URLs. Revision: planner-muse--mwolson--1.0--patch-80 * planner-bibtex.el: Use "bibtex:" rather than "bibtex://" to match bibtex URLs. Thanks to Bastien Guerry for the heads up. modified files: ChangeLog planner-bibtex.el 2005-10-29 00:01:43 GMT Michael Olson patch-79 Summary: Remove other ChangeLogs. Revision: planner-muse--mwolson--1.0--patch-79 It'd be nice if Arch could generate and maintain a merged ChangeLog of all patches that get applied from several branches, but apparently there's no good way to do this. removed files: .arch-ids/ChangeLog.sacha.id .arch-ids/ChangeLog.yh.id ChangeLog.sacha ChangeLog.yh modified files: ChangeLog renamed files: .arch-ids/ChangeLog.mwolson.id ==> .arch-ids/ChangeLog.id ChangeLog.mwolson ==> ChangeLog 2005-10-28 23:53:26 GMT Michael Olson patch-78 Summary: Install patches from Trent Buck. Revision: planner-muse--mwolson--1.0--patch-78 * debian/emacsen-install: Use the proper mechanism for installing Emacs Lisp files for Debian. * planner.el (planner-initial-page): New option that determines which page visit by default when not using day pages. (planner-use-day-pages): Refer to `planner-initial-page' in documentation. (planner-today): Visit `planner-initial-page' rather than "WelcomePage". (plan): Visit either `planner-default-page' or `planner-initial-page' rather than "WelcomePage". modified files: ChangeLog.mwolson debian/emacsen-install planner.el 2005-10-28 18:07:13 GMT Michael Olson patch-77 Summary: planner-publish: New planner-xhtml publishing style. Revision: planner-muse--mwolson--1.0--patch-77 * planner-publish.el: Miscellaneous docfixes and whitespace cleanups. (planner-xhtml-header, planner-xhtml-footer): New options that implement a header and footer for the planner-xhtml publishing style. ("planner-xhtml"): New publishing style that outputs XHTML files for Planner. modified files: ChangeLog.mwolson planner-publish.el 2005-10-20 17:39:14 GMT Michael Olson patch-76 Summary: planner-multi: Extraneous brackets fix. Revision: planner-muse--mwolson--1.0--patch-76 * planner-multi.el: Apply patch from Marco Gidde that fixes a problem with extraneous brackets. modified files: ChangeLog.mwolson planner-multi.el 2005-10-19 00:28:54 GMT Michael Olson patch-75 Summary: Minor update to Makefile. Revision: planner-muse--mwolson--1.0--patch-75 * Makefile.defs (VERSION): Update for recent Debian package. * changelog: Ditto. modified files: ChangeLog.mwolson Makefile.defs debian/changelog 2005-10-16 15:25:24 GMT Jim Ottaway patch-3 Summary: planner-multi.el Revision: planner--jeho--1.1--patch-3 * planner-multi.el (planner-multi-task-string): applied patch to make link formatting work correctly modified files: planner-multi.el 2005-10-07 02:06:09 GMT Sacha Chua patch-490 Summary: planner-accomplishments.el: Line up accomplishments neatly Revision: planner--dev--1.0--patch-490 * planner-accomplishments.el: From sacha@free.net.ph--main/planner--merge--1.0--patch-3: planner-accomplishments.el: Line up accomplishments neatly. Thanks to pll for the suggestion! modified files: planner-accomplishments.el 2005-10-05 16:39:49 GMT Peter K. Lee patch-13 Summary: changed task publishing to use ul and li Revision: planner-muse--peter--1.0--patch-13 * planner-publish.el (planner-html-markup-strings): added planner-begin-task-body, modified tasks and task to use ul and li (planner-html-style-sheet): changed default template to not include external css link. modified files: planner-publish.el 2005-09-17 04:19:09 GMT Sacha Chua patch-489 Summary: Bugfix: planner-rss.el: Add anchor- to numeric anchors Revision: planner--dev--1.0--patch-489 * planner-rss.el (planner-rss-add-note): Add anchor- to numeric anchors. This catches up with an emacs-wiki change for XHTML compliance. Thanks to Andrew Plumb for pointing this out! modified files: planner-rss.el 2005-09-25 01:18:36 GMT Michael Olson patch-70 Summary: If passed deadline, keep it rather than discarding. Revision: planner-muse--mwolson--1.0--patch-70 * planner-deadline.el (planner-deadline-days-left): Return a negative value if date is not specified and the deadline date is greater than today. The previous behavior was to return nil, which seems wrong. Thanks to Chris Parsons for the report. modified files: ChangeLog.mwolson planner-deadline.el 2005-09-22 05:17:40 GMT John Sullivan patch-23 Summary: w3m-current-title is often nil, so we also check w3m-buffer-title. Revision: planner--johnsu01--0--patch-23 modified files: planner-w3m.el 2005-09-22 05:17:40 GMT John Sullivan patch-23 Summary: w3m-current-title is often nil, so we also check w3m-buffer-title. Revision: planner--johnsu01--0--patch-23 modified files: planner-w3m.el 2005-09-08 03:40:09 GMT Sacha Chua patch-487 Summary: Bugfix: planner-multi-edit-task-description: Use new description! Revision: planner--dev--1.0--patch-487 * planner-multi.el (planner-multi-edit-task-description): Use newinfo when inserting. This makes edit-task-description work again. modified files: planner-multi.el 2005-09-08 03:05:04 GMT Sacha Chua patch-486 Summary: Bugfix: planner-multi-task-string: Fix misplaced parens Revision: planner--dev--1.0--patch-486 * planner-multi.el (planner-multi-task-string): Bugfix: Correct misplaced parens. This should check if the second item is a date. modified files: planner-multi.el 2005-09-08 02:30:35 GMT Sacha Chua patch-485 Summary: Bugfix: planner-multi-update-task: Use planner-multi-task-string Revision: planner--dev--1.0--patch-485 * planner-multi.el (planner-multi-update-task): Use planner-multi-task-string to insert the right task string for tasks that have only one plan page. modified files: planner-multi.el 2005-09-07 01:18:21 GMT John Sullivan patch-21 Summary: Added references to Emacs and Emacs Lisp manuals to explain the syntax for planner-cyclic. Revision: planner--johnsu01--0--patch-21 modified files: planner-el.texi 2005-09-05 14:56:43 GMT Michael Olson patch-66 Summary: planner-rss: Minor muse-publishing-styles fix. Revision: planner-muse--mwolson--1.0--patch-66 * planner-rss.el: Only add planner-rss and planner-rss-info to muse-publishing-styles if they don't already exist. modified files: ChangeLog.mwolson planner-rss.el 2005-09-04 15:59:47 GMT David D. Smith patch-1 Summary: integration with muse mode Revision: planner-muse--devo--1.0--patch-1 This is a first-draft implementation of RSS support for planner-muse, completely not backwards-compatible. Naturally there is a lot of room for a better implementation but the code is much smaller and simpler than the previous planner-rss.el. Hopefully this can get other people hacking. modified files: planner-rss.el 2005-09-02 23:21:19 GMT Michael Olson patch-63 Summary: Adapt for muse-url-protocol. Revision: planner-muse--mwolson--1.0--patch-63 * planner*.el: In browse-url functions, match against "\\`proto..." instead of "^proto...". When adding a new protocol, make sure it has the "://" part. * planner-bibtex.el: Remove stale reference to planner-browse-url-functions. * planner-erc.el ("[ei]rc://"): Concatenate definitions for erc and irc. * planner.el (planner-browse-url, planner-browse-url-info) (planner-browse-url-man, planner-browse-url-google) (planner-resolve-url-google, planner-set-sym-and-url-regexp) (planner-url-protocols. planner-add-protocol): Remove. (planner-visit-link): Call muse-browse-url. modified files: ChangeLog.mwolson planner-bbdb.el planner-bibtex.el planner-bookmark.el planner-erc.el planner-gnats.el planner-gnus.el planner-lisp.el planner-mhe.el planner-psvn.el planner-rmail.el planner-unix-mail.el planner-vm.el planner-wl.el planner-xtla.el planner.el 2005-09-02 20:28:35 GMT Peter K. Lee patch-11 Summary: Read-Only regions Revision: planner-muse--peter--1.0--patch-11 * planner-publish.el (planner-publish-task-tag): mark region as read-only as recommended by Michael Olson. (planner-publish-note-tag): same as above * planner-timeclock-summary.el (planner-timeclock-summary-update): changed so that even if there is an error with timelog file (which happens frequently), you don't lose the * Timeclock section. * planner.el (planner-create-note-from-context): write this later... modified files: ChangeLog.mwolson planner-publish.el planner-timeclock-summary.el planner.el 2005-09-01 16:26:09 GMT Michael Olson patch-62 Summary: Begin list items with " - " instead of "- ". Revision: planner-muse--mwolson--1.0--patch-62 * planner-authz.el (planner-authz-markup-task): Handle case where we have extra whitespace after the dash. * planner-notes-index.el (planner-notes-index-tag, planner-notes-index): Use " - " to begin list items rather than "- ". modified files: ChangeLog.mwolson planner-authz.el planner-notes-index.el 2005-09-01 16:15:36 GMT Michael Olson patch-61 Summary: Use a more standard root element. Revision: planner-muse--mwolson--1.0--patch-61 * planner-publish.el (planner-xml-header): Use instead of , as suggested by Brad Collins. modified files: ChangeLog.mwolson planner-publish.el 2005-09-01 13:38:38 GMT Michael Olson patch-60 Summary: Allow Planner to visit links to temporary files. Revision: planner-muse--mwolson--1.0--patch-60 * planner.el (planner-visit-link): Apply patch from Marco Gidde that allows Planner to visit a link to a temporary file by visiting its buffer. This patch is not needed upstream, hence the muse-only tag in this commit message. modified files: ChangeLog.mwolson planner.el 2005-08-31 15:34:57 GMT Sacha Chua patch-484 Summary: Bugfix: planner-delete-task and planner-edit-task-description-basic when linked tasks do not exist Revision: planner--dev--1.0--patch-484 * planner.el: Thanks to Sergey Vlasov for the patches! (planner-delete-task): Make sure task is found before deleting. (planner-edit-task-description-basic): Use new description instead of old one. modified files: planner.el 2005-08-31 14:48:02 GMT Sacha Chua patch-483 Summary: Bugfix: planner-multi-replan-task should suggest only plan pages Revision: planner--dev--1.0--patch-483 * planner-multi.el (planner-multi-task-string): New convenience function that determines the right task line. (planner-multi-replan-task): Bugfix: Suggest only plan pages. Work with nil. Thanks to John Sullivan for suggesting this! * planner.el (planner-replan-task): Use alias mechanism instead of function variable. modified files: planner-multi.el planner.el 2005-08-31 13:23:58 GMT Sacha Chua patch-482 Summary: Bugfix: planner-multi-task-xref: Use planner-replan-task Revision: planner--dev--1.0--patch-482 * planner-multi.el (planner-task-info-from-string): Always add current page to link list. This should simplify case for planner-multi. (planner-multi-task-xref): Rewrite to use planner-replan-task. This should fix the bug reported by Paul Lussier. modified files: planner-multi.el 2005-08-31 12:12:49 GMT Sacha Chua patch-481 Summary: Bugfix: planner-timeclock-summary-day-range-entry: Accept functions again Revision: planner--dev--1.0--patch-481 * planner-timeclock-summary.el (planner-timeclock-summary-day-range-entry): Merge Chris Parsons' patch restoring the use of functions. modified files: planner-timeclock-summary.el 2005-08-26 00:03:03 GMT Sacha Chua patch-480 Summary: Bugfix: planner-extract-tasks should use planner-line-beginning-position Revision: planner--dev--1.0--patch-480 * planner.el (planner-extract-tasks): Use planner-line-beginning-position and line-end-position. Thanks to Michael Olson for spotting this! modified files: planner.el 2005-08-26 00:00:31 GMT Sacha Chua patch-479 Summary: planner-multi-task-date bugfix: Fix matching finally! Revision: planner--dev--1.0--patch-479 * planner-multi.el (planner-multi-task-date): Merge Sergey Vlasov's bugfix for lists with dates in them. * planner.el (planner-list-diary-entries): Change require to 'diary-lib. Thanks to Sergey for pointing this out! modified files: planner-multi.el planner.el 2005-08-25 13:05:50 GMT Sacha Chua patch-478 Summary: Bugfix: planner-task-info-from-string: Make sure link is non-nil before string-matching Revision: planner--dev--1.0--patch-478 * planner.el (planner-task-info-from-string): Check if link is nil before string-matching it. modified files: planner.el 2005-08-25 13:03:49 GMT Sacha Chua patch-477 Summary: planner-multi-task-date bugfix: Be careful about links Revision: planner--dev--1.0--patch-477 * planner-multi.el (planner-multi-task-date): Be a lot more careful about the date so that non-date links don't get picked up. modified files: planner-multi.el planner.el 2005-08-25 12:48:21 GMT Sacha Chua patch-476 Summary: planner.el: Remove exit-calendar compile advice, and uncollapse outline Revision: planner--dev--1.0--patch-476 * planner.el (exit-calendar): Remove compile flag. Thanks to Sergey Vlasov for spotting this! * planner.el: Oops, forgot to uncollapse the outline. Must remember to call allout-show-all before saving planner.el modified files: planner.el 2005-08-25 12:29:10 GMT Sacha Chua patch-475 Summary: Merge planner-cyclic and planner-multi bugfixes from Sergey Vlasov Revision: planner--dev--1.0--patch-475 * planner-cyclic.el: Add Sergey Vlasov to copyright. (planner-cyclic-task-description-format): New variable. (planner-cyclic-generate-task): Use task description format. (planner-cyclic-create-task-maybe): Make sure date is included. (planner-cyclic-get-cyclic-tasks): Use planner-list-diary-entries. * planner-multi.el (planner-multi-task-date): Use specified task date first, if detected. (planner-task-date): Remove need for advice by using aliases. * planner.el: Add Sergey Vlasov to copyright. Move function from planner-cyclic. (planner-list-diary-entries): New function tries to preserve diary display as much as possible. modified files: planner-cyclic.el planner-multi.el planner.el 2005-08-20 14:53:31 GMT Sacha Chua patch-474 Summary: Bugfix: planner-appt-mark-calendar shouldn't call planner-appt-filename-to-date Revision: planner--dev--1.0--patch-474 * planner-appt.el (planner-appt-mark-calendar): Merge Sergey Vlasov's bugfix for obsolete call to planner-appt-filename-to-date. modified files: planner-appt.el 2005-08-19 15:12:38 GMT Sacha Chua patch-471 Summary: Bugfix: with-planner: Defer evaluation of planner-derived-mode-p Revision: planner--dev--1.0--patch-471 * planner.el (with-planner): Merge patch moving planner-derived-mode-p test into with-planner body. Thanks to Sergey Vlasov for the patch! modified files: planner.el 2005-08-18 06:22:11 GMT John Sullivan patch-19 Summary: Get the mwolson archive address right, for real. Revision: planner--johnsu01--0--patch-19 modified files: planner-el.texi 2005-08-18 06:15:28 GMT John Sullivan patch-18 Summary: Fixed pxref in node. Fleshed out and added cindex entries around it. Revision: planner--johnsu01--0--patch-18 modified files: planner-el.texi 2005-08-18 06:04:47 GMT John Sullivan patch-17 Summary: Corrected installation instructions for registering and pulling from the tla emacs-wiki archive. We were still saying 2004, should be 2005. Revision: planner--johnsu01--0--patch-17 modified files: planner-el.texi 2005-08-18 05:55:06 GMT John Sullivan patch-16 Summary: Change name of node and menu item from Changing Tasks to Modifying tasks, since Changing Tasks has other meanings in the context of workflow and timeclock. Add some helpful related index entries. Revision: planner--johnsu01--0--patch-16 modified files: planner-el.texi 2005-08-14 15:22:52 GMT Sacha Chua patch-470 Summary: Bugfix: planner-save-buffers: Check if buffer is associated with a file Revision: planner--dev--1.0--patch-470 * planner.el (planner-save-buffers): Check if buffer is associated with file. Fixes notes-index saving bug reported by John Sullivan. modified files: planner.el 2005-08-13 14:31:24 GMT Sacha Chua patch-469 Summary: planner-deadline bugfix: Avoid infinite loops by calculating deadlines as we insert them Revision: planner--dev--1.0--patch-469 * planner-deadline.el (planner-deadline-days-left): Accept strings for dates. (planner-deadline-calculate-string): New convenience function removes the need to call planner-deadline-update after changing the deadline. (planner-deadline-update): Call convenience function instead of using planner-deadline-update. This fixes the endless looping bug that happens when you have deadlines on more than one page. modified files: planner-deadline.el 2005-08-12 23:35:40 GMT Peter K. Lee patch-10 Summary: publish task links now Revision: planner-muse--peter--1.0--patch-10 * planner-publish.el (planner-html-markup-strings): add a little something for task link to get published (planner-publish-task-tag): pull in link plan date from attributes, although we only use link. And well, create the link text and put it in there! modified files: planner-publish.el 2005-08-12 22:19:51 GMT Peter K. Lee patch-9 Summary: fixup note publishing to include anchor, timestamp, links Revision: planner-muse--peter--1.0--patch-9 * planner-publish.el: Thanks to Chris McMahan for the patch to publish notes properly! (planner-html-markup-strings): add extra strings for marking up notes to html. now notes publish with tags and links correctly. (planner-publish-notes-tag): the end marker was incorrect when markup-region was complete. (planner-publish-note-tag): notes publish with anchor references as well as timestamp and links! modified files: planner-publish.el 2005-08-12 18:53:16 GMT Peter K. Lee patch-7 Summary: fix timeclock entry with planner-multi continue publishing :before hook Revision: planner-muse--peter--1.0--patch-7 * planner-publish.el (planner-publish-prepare-buffer): must return nil to allow it to continue processing by other hooks * planner-timeclock.el (planner-timeclock-plan-string): fixed issue where planner-multi is included in featurep, but not necessary used in planner tasks. Prevent 'Not Planned' classification on tasks that *do* have plan association. * planner-timeclock-summary.el (planner-timeclock-summary-make-text-table-day): if empty, show No Entries modified files: planner-publish.el planner-timeclock-summary.el planner-timeclock.el 2005-08-10 00:46:00 GMT Michael Olson patch-53 Summary: Make use of BUILDOPTS. Revision: planner-muse--mwolson--1.0--patch-53 * Makefile.defs (BUILDOPTS): New variable indicating extra options to be passed to dpkg-buildpackage. * Makefile (debrelease): Use $(BUILDOPTS). modified files: ChangeLog.mwolson Makefile Makefile.defs 2005-08-09 23:00:32 GMT Michael Olson patch-52 Summary: Make generated Debian packages slightly easier to upload. Revision: planner-muse--mwolson--1.0--patch-52 * debian/changelog: Generate 3.30.arch.52-1. * debian/control (Description): Clarify that this a port of Planner. * debian/rules (clean): Call $(MAKE) realclean instead of $(MAKE) clean. * Makefile.defs (LASTUPLOAD): New variable that indicates the version that was last uploaded to Debian. * Makefile (debrelease): Use $(LASTUPLOAD) to ensure that a full set of changes is generated. This means we have to use dpkg-buildpackage, since debuild doesn't recognize the environment variables that it claims to recognize. modified files: ChangeLog.mwolson Makefile Makefile.defs debian/changelog debian/control debian/rules 2005-08-09 07:09:40 GMT Michael Olson patch-51 Summary: Update the Debian package. Revision: planner-muse--mwolson--1.0--patch-51 modified files: ChangeLog.mwolson Makefile.defs debian/changelog 2005-08-09 07:07:25 GMT Michael Olson patch-50 Summary: Remove old code sections. Revision: planner-muse--mwolson--1.0--patch-50 * planner.el: Remove commented-out sections. * scripts/planner-build.el (load-path): Use my path to Muse. Others can edit it as they will in their own branches :^) . modified files: ChangeLog.mwolson planner.el scripts/planner-build.el 2005-08-09 06:13:56 GMT Michael Olson patch-48 Summary: Debian tweaks. Revision: planner-muse--mwolson--1.0--patch-48 * Makefile.defs (VERSION): Update for another snapshot. * debian/conffile: Removed, since it causes a "duplicate conffile" error. * debian/control: Add trailing newline. * debian/rules: Set DH_COMPAT to 3 to make warnings go away. Correct directory to install elisp files to. removed files: debian/.arch-ids/conffiles.id debian/conffiles modified files: ChangeLog.mwolson Makefile.defs debian/changelog debian/control debian/rules 2005-08-09 05:22:29 GMT Michael Olson patch-47 Summary: Prepare initial Debian package for planner-muse-el. Revision: planner-muse--mwolson--1.0--patch-47 * Makefile.defs (ELISPDIR, VERSION): Adapt for planner-muse build. * debian/README.Debian: Add note about Muse port. * debian/changelog: Prepare package planner-muse-el 3.30.arch.47-1. * debian/conffiles: Adapt for planner-muse. * debian/control (Source, Maintainer, Standards-Version, Package) (Depends, Description): Ditto. * debian/emacsen-install, debian/emacsen-remove, debian/emacsen-startup: Ditto. * debian/rules: Simplify and adapt for planner-muse. modified files: ChangeLog.mwolson Makefile.defs debian/README.Debian debian/changelog debian/conffiles debian/control debian/emacsen-install debian/emacsen-remove debian/emacsen-startup debian/rules 2005-08-09 04:09:22 GMT Michael Olson patch-46 Summary: Implement Makefile system and include Debian files. Revision: planner-muse--mwolson--1.0--patch-46 * planner.el (planner-derived-mode-p): Wrap in `eval-and-compile' in order to silence a fatal compiler error. (planner-url-protocols): Use `eval-when-compile' to avoid a compiler warning. * Makefile: New file that builds Planner. * Makefile.defs: New file that contains Makefile variable definitions. * scripts/planner-build.el: New file that aids in the Planner building process. It adds the correct directories to the load-path and provides a `planner-elint-files' function that works in conjunction with the Makefile's `test' target. * debian: New directory containing the files used in building Debian packages for Planner. new files: .arch-ids/Makefile.defs.id .arch-ids/Makefile.id Makefile Makefile.defs debian/.arch-ids/=id debian/.arch-ids/README.Debian.id debian/.arch-ids/changelog.id debian/.arch-ids/conffiles.id debian/.arch-ids/control.id debian/.arch-ids/copyright.id debian/.arch-ids/emacsen-install.id debian/.arch-ids/emacsen-remove.id debian/.arch-ids/emacsen-startup.id debian/.arch-ids/planner-el.docs.id debian/.arch-ids/rules.id debian/README.Debian debian/changelog debian/conffiles debian/control debian/copyright debian/emacsen-install debian/emacsen-remove debian/emacsen-startup debian/planner-el.docs debian/rules scripts/.arch-ids/=id scripts/.arch-ids/planner-build.el.id scripts/planner-build.el modified files: ChangeLog.mwolson planner.el new directories: debian debian/.arch-ids scripts scripts/.arch-ids 2005-08-08 18:35:21 GMT Peter K. Lee patch-5 Summary: html inner-header and inner-footer as well as better timeclock summary format table output Revision: planner-muse--peter--1.0--patch-5 * planner-accomplishments.el (planner-accomplishments-format-table): call planner-align-table routine * planner-publish.el (planner-html-header): include inner-header section * planner-publish.el (planner-html-footer): include inner-footer section * planner-timeclock-summary.el (planner-timeclock-summary-make-text-table-day): call planner-align-table routine for table formatting * planner.el: added planner-align-table routine which does a better job of displaying and publishing tables taking into account links which hide invisible link wrapper characters modified files: planner-accomplishments.el planner-publish.el planner-timeclock-summary.el planner.el 2005-08-07 15:17:09 GMT Sacha Chua patch-468 Summary: Bugfix: planner-notes-index should be in Planner project Revision: planner--dev--1.0--patch-468 * planner-notes-index.el (planner-notes-index): Make sure pages are in Planner context. This resolves the emacs-wiki-visit-link problem. Thanks to Kohkichi Hosoda for pointing this out! modified files: planner-notes-index.el 2005-08-06 07:42:48 GMT Michael Olson patch-44 Summary: Fix error in planner-annotation-from-wiki. Revision: planner-muse--mwolson--1.0--patch-44 * planner.el (planner-annotation-from-wiki): Fix type error. modified files: ChangeLog.mwolson planner.el 2005-08-06 04:01:03 GMT Sacha Chua patch-467 Summary: Bugfix: planner-timeclock should always work within Planner context to properly deal with some tasks Revision: planner--dev--1.0--patch-467 * planner-timeclock-summary.el (planner-timeclock-summary-extract-data): Ensure Planner context. This solves the planner-multi problem with numbered pages reported by Karen Cooke. * planner-timeclock.el (planner-timeclock-task-info): Make sure this is always evaluated within the Planner context. * planner.el (planner-find-task-basic): Anchor regular expression at start of string. modified files: planner-timeclock-summary.el planner-timeclock.el planner.el 2005-08-02 15:01:07 GMT Sacha Chua patch-466 Summary: NOTE: planner-create-section-function, planner-create-at-top, planner-create-at-bottom: RENAMED FROM planner-seek- Revision: planner--dev--1.0--patch-466 * planner.el (planner-create-section-function): NOTE: Rename from planner-seek-section-function. Thanks to John Sullivan for pointing out inconsistency. (planner-create-at-top): Rename from planner-seek-create-at-top. (planner-create-at-bottom): Rename from planner-seek-create-at-bottom. (planner-narrow-to-section): Use planner-create-section-function. (planner-seek-to-first): Use planner-create-section-function. modified files: planner.el 2005-08-02 00:06:57 GMT Peter K. Lee patch-4 Summary: publish and buffer alignment display change for timeclock summary Revision: planner-muse--peter--1.0--patch-4 * planner-timeclock-summary.el (planner-timeclock-summary-make-text-table-day): changed basis of code back to align-regexp call. Instead of complex alignment handling, we just go through once more at the end and add a few more spaces to make the column with links show up properly in the planner-mode buffer. Furthermore, the changes allows muse publishing to display the timeclock summary table properly. modified files: planner-publish.el planner-timeclock-summary.el 2005-08-01 19:04:59 GMT Peter K. Lee patch-2 Summary: planner publish html styles and extensions improvements Revision: planner-muse--peter--1.0--patch-2 * planner-publish.el (planner-html-markup-strings): p tags close prematurely due to some other auto closing call... just use div tags. (planner-html-style-sheet): added pretty table style now, the default style-sheet is cleaner, should always be over-ridden. (planner-html-header): changed the default header to include planner-html-embedded-header for easier inclusion of custom header content w/o overriding the entire header. (planner-html-embedded-header): new (planner-html-embedded-footer): new (planner-publish-markup-note): markup content tag with newline to avoid post cleanup to consider it as part of text. modified files: planner-publish.el 2005-07-29 21:08:07 GMT Sacha Chua patch-465 Summary: planner-notes-index: Fix to work with files in subdirectories Revision: planner--dev--1.0--patch-465 * planner-notes-index.el (planner-notes-index-headlines-on-page): Work with files in subdirectories. (planner-notes-index-headlines-in-range): Use planner-get-day-pages. (planner-notes-index-years): Docfix. modified files: planner-notes-index.el 2005-07-28 13:04:09 GMT Sacha Chua patch-464 Summary: Bugfixes: Byte-compile properly (missing planner-link-name, bug in planner-annotation-from-file) Revision: planner--dev--1.0--patch-464 * planner.el (planner-link-name): Add missing alias. Thanks to Wei-Hao Lin for spotting this. (planner-annotation-from-file): Fix misplaced parenthesis. * planner-ical.el (planner-ical-export): Add missing variables. modified files: planner-ical.el planner.el 2005-07-27 22:41:06 GMT Sacha Chua patch-463 Summary: Bugfix: planner-current-note-info: Recognize multi properly again Revision: planner--dev--1.0--patch-463 * planner.el (planner-current-note-info): Add missing closing paren. Thanks to Sven Kloppenburg for the patch! This fixes remembering to multiple pages. modified files: planner.el 2005-07-26 14:46:18 GMT Sacha Chua patch-462 Summary: Bugfix: Add missing planner-link-target. New option: planner-calendar-nop-buttons-flag Revision: planner--dev--1.0--patch-462 * planner.el (planner-link-target): Add missing alias. * planner-calendar.el (planner-calendar-nop-buttons-flag): New option. (planner-calendar): Use planner-calendar-nop-buttons-flag. (planner-calendar-published-file-href): Make sure is needed. modified files: planner-calendar.el planner.el 2005-07-26 13:33:26 GMT Sacha Chua patch-461 Summary: Bugfix: planner-visit-link: Add missing alias Revision: planner--dev--1.0--patch-461 * planner.el (planner-visit-link): Add missing alias. Thanks to Zak for pointing this out! modified files: planner.el 2005-07-25 14:42:14 GMT Sacha Chua patch-460 Summary: Bugfix: planner-calendar-published-file-href: Stop refreshing the file list all the time Revision: planner--dev--1.0--patch-460 * planner.el (planner-page-file): Don't change projects, as the underlying functions use variables properly. * planner-calendar.el (planner-calendar-published-file-href): Don't keep refreshing the file alist. This should make it faster. Thanks to drkm for pointing this out. modified files: planner-calendar.el planner.el 2005-07-25 14:28:13 GMT Sacha Chua patch-459 Summary: Bugfix: planner-calendar: Do not over-pad months that end with Sunday Revision: planner--dev--1.0--patch-459 * planner-calendar.el (planner-calendar): Merge small patch from drkm to fix planner-calendar boundary case when last day of the month is Sunday. modified files: planner-calendar.el 2005-07-25 15:08:09 GMT Peter K. Lee patch-1 Summary: planner publishing tree Revision: planner-muse--peter--1.0--patch-1 * planner.el: get rid of publishing specific code from planner. Added planner-publish.el which creates new Muse style for publishing planner specific files. new files: .arch-ids/planner-publish.el.id planner-publish.el modified files: planner.el 2005-07-23 20:08:09 GMT Sacha Chua patch-457 Summary: Docfix: Fix iCal example quotes Revision: planner--dev--1.0--patch-457 * planner-el.texi (iCal Task Publication): Bugfix: Fix quotes. modified files: ChangeLog planner-el.texi 2005-07-23 20:03:36 GMT Sacha Chua patch-456 Summary: New: planner-ical.el Revision: planner--dev--1.0--patch-456 * planner-ical.el: Add planner-ical.el from Chris Parsons. (planner-ical-export-this-page): New. (planner-ical-export-page): Add FILE argument. * planner-el.texi (iCal Task Publication): Document planner-ical. new files: .arch-ids/planner-ical.el.id planner-ical.el modified files: ChangeLog planner-el.texi 2005-07-23 19:50:37 GMT Sacha Chua patch-455 Summary: Bugfix: planner-rss-add-note: Remove tags from title Revision: planner--dev--1.0--patch-455 * planner-rss.el (planner-rss-strip-tags): New function. (planner-rss-add-note): Remove all tags from title. modified files: ChangeLog planner-rss.el 2005-07-21 15:44:28 GMT Yann Hodique patch-41 Summary: Bugfix Revision: planner--yh--1.0--patch-41 * planner.el (planner-annotation-from-file): missing closing paren :( modified files: ChangeLog.yh planner.el 2005-07-20 23:40:54 GMT Yann Hodique patch-40 Summary: Fix minor bug un planner-multi.el Revision: planner--yh--1.0--patch-40 * planner-multi.el (planner-multi-copy-or-move-task): use planner-multi-make-link instead of planner-make-link modified files: ChangeLog.yh planner-multi.el 2005-07-20 23:17:54 GMT Yann Hodique patch-39 Summary: Fix incorrect behavior for planner-multi-remove-task-from-pool Revision: planner--yh--1.0--patch-39 * planner-multi.el (planner-multi-task-xref): use muse-explicit-link-regexp (planner-multi-remove-task-from-pool): fix incorrect task replanning modified files: ChangeLog.yh planner-multi.el 2005-07-20 22:25:54 GMT Yann Hodique patch-38 Summary: Make planner-directory a function Revision: planner--yh--1.0--patch-38 planner-directory is now a function to read muse project information modified files: ChangeLog.yh planner-export-diary.el planner-id.el planner-notes-index.el planner-report.el planner-tasks-overview.el planner.el 2005-07-20 15:46:12 GMT Michael Olson patch-35 Summary: Highlight links in note headings. Revision: planner-muse--mwolson--1.0--patch-35 * planner.el (planner-highlight-notes): Don't apply planner-note-headline-face to parentheses and link. Thanks to Chris McMahan for the report. modified files: ChangeLog.mwolson planner.el 2005-07-18 17:52:27 GMT Sacha Chua patch-453 Summary: planner-create-note: Default to current page when called interactively Revision: planner--dev--1.0--patch-453 * planner.el (planner-create-note): Default to current page. Thanks to Janne Hellsten for suggesting this. modified files: ChangeLog planner.el 2005-07-17 04:10:37 GMT Sacha Chua patch-452 Summary: Add autoload cookies to a bunch of files, remove planner-appt-filename-to-date Revision: planner--dev--1.0--patch-452 * planner.el (planner-goto-most-recent): Fix redundant function. * planner-appt.el (planner-appt-filename-to-date): Remove function, use planner-filename-to-calendar-date instead. modified files: ChangeLog planner-appt.el planner-authz.el planner-bibtex.el planner-cyclic.el planner-deadline.el planner-diary.el planner-export-diary.el planner-id.el planner-ledger.el planner-log-edit.el planner-multi.el planner-notes-index.el planner-psvn.el planner-rank.el planner-rdf.el planner-report.el planner-rss.el planner-schedule.el planner-tasks-overview.el planner-timeclock-summary-proj.el planner-timeclock-summary.el planner-timeclock.el planner-trunk.el planner-w3m.el planner-xtla.el planner.el 2005-07-16 15:50:24 GMT Sacha Chua patch-451 Summary: planner-timeclock-summary-make-text-table-day: Format projects as links Revision: planner--dev--1.0--patch-451 * planner-timeclock-summary.el: Remove commented-out cruft. (planner-timeclock-summary-make-text-table-day): Format projects as links. Thanks to Trent Buck for suggesting this. (planner-timeclock-summary-generate-report): Fix report here also. (planner-timeclock-summary-make-summary-string-range): Replace with more compact test. (planner-timeclock-summary-make-text-table-day): Include properly padded links with fake alignment. (planner-timeclock-summary-generate-report): NOTE: Remove obsolete function. * planner.el (planner-sort-tasks-basic): Add failsafe for unrecognized priorities, although this really shouldn't happen. Thanks to pll for pointing this out. * planner-timeclock.el (planner-timeclock-task-info): Parse strings as well. modified files: ChangeLog planner-timeclock-summary.el planner-timeclock.el planner.el 2005-07-15 22:17:48 GMT Yann Hodique patch-36 Summary: Use planner-make-link instead of hard-coded brackets Revision: planner--yh--1.0--patch-36 Fix some incorrect usage of planner links pattern modified files: ChangeLog.yh planner-bbdb.el planner-psvn.el planner-xtla.el planner.el 2005-07-15 04:56:35 GMT Michael Olson patch-33 Summary: Minor caadr -> car cadr fixup. Revision: planner-muse--mwolson--1.0--patch-33 * planner-xtla.el (planner-xtla-url-transform): Use (car (cadr ...)) rather than (caadr ...) since some Emacsen can't handle that. modified files: ChangeLog.mwolson planner-xtla.el 2005-07-14 22:55:15 GMT Yann Hodique patch-34 Summary: Fix false heading lines in notes, from planner-xtla Revision: planner--yh--1.0--patch-34 * planner-xtla.el (planner-xtla-log-edit-add-note): lines beginning with * should really be list items modified files: ChangeLog.yh planner-xtla.el 2005-07-14 21:32:16 GMT Yann Hodique patch-33 Summary: Fix error in planner-xtla-url-transform Revision: planner--yh--1.0--patch-33 * planner-xtla.el (planner-xtla-url-transform): fix base url retreival modified files: ChangeLog.yh planner-xtla.el 2005-07-14 19:17:19 GMT Michael Olson patch-31 Summary: Replace a few emacs-wiki functions in planner-report. Revision: planner-muse--mwolson--1.0--patch-31 * planner-report.el (planner-report-generate, planner-report-generate): Use planner-specific functions rather than emacs-wiki functions. modified files: ChangeLog.mwolson planner-report.el 2005-07-14 13:20:07 GMT Yann Hodique patch-31 Summary: Fix bug #2647 Revision: planner--yh--1.0--patch-31 * planner-timeclock.el (planner-timeclock-task-info): use muse-explicit-link-regexp instead of emacs-wiki stuff modified files: ChangeLog.yh planner-timeclock.el 2005-07-13 19:16:10 GMT Michael Olson patch-28 Summary: Make planner-xtla-url-transform work again. Revision: planner-muse--mwolson--1.0--patch-28 * planner-xtla.el (planner-xtla-url-transform): Ignore other args. Thanks to Peter K. Lee for the report! modified files: ChangeLog.mwolson planner-xtla.el 2005-07-13 15:04:39 GMT Yann Hodique patch-29 Summary: Fix bug #2638 : Extra set of brackets around page references in newly-created tasks Revision: planner--yh--1.0--patch-29 This is a side-effect of making planner-make-link generate valid links when given a valid link as input modified files: ChangeLog.yh planner.el 2005-07-13 04:26:47 GMT Sacha Chua patch-450 Summary: planner-current-note-info: Be stricter with note links Revision: planner--dev--1.0--patch-450 * planner.el (planner-current-note-info): Be a lot stricter with note links to prevent (C-c a) from being recognized as a note link. Thanks to Xavier Maillard for reporting this bug. modified files: ChangeLog planner.el 2005-07-11 07:52:59 GMT Sacha Chua patch-449 Summary: planner-calendar-create-today-link: Use make-symbolic-link Revision: planner--dev--1.0--patch-449 * planner-calendar.el (planner-calendar-create-today-link): Use make-symbolic-link because that's the Right Thing to Do. Thanks to Angus Lees for the suggestion. modified files: ChangeLog planner-calendar.el 2005-07-10 03:16:23 GMT Sacha Chua patch-448 Summary: Add p-create-task and p-create-task-from-buffer to planner-auto Revision: planner--dev--1.0--patch-448 * planner-auto.el: Add planner-create-task and planner-create-task-from-buffer. Thanks to drkm for pointing this out. modified files: ChangeLog planner-auto.el 2005-07-10 03:13:15 GMT Sacha Chua patch-447 Summary: Bugfix: planner-calendar-create-today-link: Quote shell arguments Revision: planner--dev--1.0--patch-447 * planner-calendar.el (planner-calendar-create-today-link): Quote argument to shell. Thanks to drkm for pointing this out. modified files: ChangeLog planner-calendar.el 2005-07-08 05:12:47 GMT Michael Olson patch-24 Summary: Fix insertion of diary entries and complaints about `emacs-wiki-link-base'. Revision: planner-muse--mwolson--1.0--patch-24 * planner-diary.el (planner-diary-get-name): Use `planner-page-name'. No need to reinvent the wheel. This should fix a diary insertion problem when using a Muse file extension. * planner-multi.el (planner-task-plan): Use `planner-link-base' instead of `emacs-wiki-link-base'. modified files: ChangeLog.mwolson planner-diary.el planner-multi.el 2005-07-07 16:53:27 GMT Sacha Chua patch-446 Summary: planner-gnus-insinuate: Change keybinding to C-c C-t Revision: planner--dev--1.0--patch-446 * planner-gnus.el (planner-gnus-insinuate): Change keybinding for planner-gnus. Thanks to drkm for the suggestion. * planner-el.texi (Gnus): Document new keybinding. modified files: ChangeLog planner-el.texi planner-gnus.el 2005-07-07 06:11:30 GMT Yann Hodique patch-25 Summary: Fix pages from planner-multi Revision: planner--yh--1.0--patch-25 For some reason, the links broke again modified files: ChangeLog.yh planner-multi.el 2005-07-06 07:13:17 GMT Michael Olson patch-21 Summary: Use `muse-publishing-current-file'. Revision: planner-muse--mwolson--1.0--patch-21 * planner.el (planner-current-file): Use `muse-publishing-current-file' instead of `muse-current-file'. modified files: ChangeLog.mwolson planner.el 2005-07-05 20:36:34 GMT Yann Hodique patch-21 Summary: don't use pos:// url as description Revision: planner--yh--1.0--patch-21 * planner.el (planner-annotation-from-file-with-position): put filename as description modified files: ChangeLog.yh planner-multi.el planner.el 2005-07-05 17:24:36 GMT Sacha Chua patch-445 Summary: Bugfix: planner-multi-link-delete: Preserve order Revision: planner--dev--1.0--patch-445 * planner-multi.el (planner-multi-link-delete): Docfix. Preserve order. Thanks to Chris Parsons for pointing out this bug. modified files: ChangeLog planner-multi.el planner-timeclock-summary.el planner.el 2005-07-04 23:03:13 GMT Michael Olson patch-19 Summary: Use muse-explicit-link-regexp instead of muse-link-regexp. Revision: planner-muse--mwolson--1.0--patch-19 * planner-multi.el (planner-multi-task-xref, planner-copy-or-move-task) (planner-multi-task-delete-this-page, planner-multi-note-xref) (planner-multi-note-xref, planner-multi-note-delete-this-page): Use `muse-explicit-link-regexp' instead of `muse-link-regexp'. * planner.el (planner-link-base, planner-link-target, planner-link-name) (planner-notes-tag): Ditto. (planner-visit-link): Detabify. modified files: ChangeLog.mwolson planner-multi.el planner.el 2005-07-04 06:44:44 GMT Sacha Chua patch-444 Summary: Bugfix: planner-multi-replan-task: Deal with tasks without dates Revision: planner--dev--1.0--patch-444 * planner-multi.el (planner-multi-replan-task): Bugfix: Deal with tasks without dates. modified files: ChangeLog planner-multi.el 2005-07-04 06:30:07 GMT Sacha Chua patch-443 Summary: New: planner-gnats.el adds support for the GNU bugtracking system Revision: planner--dev--1.0--patch-443 * planner-gnats.el: New protocol from Jeremy Cowgar. Gnats is the GNU bug tracking system. * planner-el.texi (Tracking Development): Renamed from Logs and Version Control. (Gnats): Document planner-gnats.el new files: .arch-ids/planner-gnats.el.id planner-gnats.el modified files: ChangeLog planner-el.texi 2005-07-04 02:03:35 GMT Sacha Chua patch-442 Summary: planner-save-buffers: Do not kill non-planner-mode buffers Revision: planner--dev--1.0--patch-442 * planner.el (planner-save-buffers): Move buffer killing inside test for planner-mode. Thanks to Win Treese for the patch. modified files: ChangeLog planner.el 2005-07-03 19:33:09 GMT Yann Hodique patch-20 Summary: fix links in planner-multi Revision: planner--yh--1.0--patch-20 * planner-multi.el (planner-multi-read-name): don't generate extra link marks modified files: ChangeLog.yh planner-multi.el 2005-07-03 07:46:19 GMT Yann Hodique patch-19 Summary: bugfix Revision: planner--yh--1.0--patch-19 * planner.el (planner-prepare-file): planner-file-name may be nil use planner-file-name instead of muse-file-name modified files: ChangeLog.yh planner.el 2005-07-02 15:10:37 GMT Sacha Chua patch-441 Summary: Bugfix: planner-save-buffers should suppress planner-id Revision: planner--dev--1.0--patch-441 * planner.el (planner-save-buffers): Supress planner-id fixing in automatically-saved pages. Thanks to Edgar Gonçalves for helping track down this bug. modified files: ChangeLog planner.el 2005-07-01 11:19:28 GMT Sacha Chua patch-440 Summary: Fixes planner-timeclock + planner-multi, also planner-multi-update-task Revision: planner--dev--1.0--patch-440 * planner-timeclock.el (planner-timeclock-task-marked): Use planner-timeclock-plan-string to deal with multi tasks. (planner-replan-task, planner-edit-task-description, (planner-timeclock-task-info): Deal with planner-multi tasks. (planner-timeclock-plan-string): Convenience function for easier formatting. * planner-timeclock-summary.el (planner-timeclock-summary-extract-data): Use new functions available in planner-timeclock.el to default to the first plan in a task. (planner-timeclock-summary-extract-task-data): Remove. * planner.el (planner-task-info-override): New. * planner-multi.el (planner-multi-remove-task-from-pool): Call standard replan task function to trigger advice. (planner-edit-task-description): Remove crufty and miscopied advice. modified files: ChangeLog planner-multi.el planner-timeclock-summary.el planner-timeclock.el planner.el 2005-07-01 03:50:19 GMT Sacha Chua patch-439 Summary: Bugfix: planner-lower-task: typo Revision: planner--dev--1.0--patch-439 * planner.el (planner-lower-task): Fix typo. Thanks to Michael Olson for the patch. modified files: ChangeLog planner.el 2005-07-01 03:40:27 GMT Sacha Chua patch-438 Summary: Bugfix: planner-update-wiki-project: planner-name-regexp fix, planner-save-buffers SKIP-BUFFERS Revision: planner--dev--1.0--patch-438 * planner.el (planner-update-wiki-project): Avoid adding planner-name-regexp multiple times. This solves the regexp too large error. * planner.el (planner-save-buffers): Add SKIP-BUFFER argument to make it easier to preserve cursor position, etc. when marking a task complete. modified files: ChangeLog planner.el 2005-06-30 13:14:12 GMT Sacha Chua patch-437 Summary: Bugfix: planner-derived-mode-p should pass the modes to derived-mode-p Revision: planner--dev--1.0--patch-437 * planner.el (planner-derived-mode-p): Bugfix: Work for GNU Emacs which expects a list for derived-mode-p. Thanks to Edgar.Goncalves for pointing this out. modified files: ChangeLog planner.el 2005-06-30 11:51:10 GMT Sacha Chua patch-436 Summary: Bugfix: planner-multi-tasks-equal-p: Deal with tasks without link text Revision: planner--dev--1.0--patch-436 * planner-multi.el (planner-multi-tasks-equal-p): Deal with tasks without link text. Solves nil backtrace when you update a task without links. (planner-multi-edit-task-description): Fix typo. modified files: ChangeLog planner-multi.el 2005-06-30 07:21:53 GMT Sacha Chua patch-434 Summary: planner-sort-tasks: Be paranoid about task sorting Revision: planner--dev--1.0--patch-434 * planner.el (planner-sort-tasks): Go back to old task if called from a task, or to old point if not. modified files: ChangeLog planner.el 2005-06-30 06:43:52 GMT Sacha Chua patch-433 Summary: Bugfix: Remove parens around planner-calendar-html-tag-marker Revision: planner--dev--1.0--patch-433 * planner-calendar.el (planner-calendar-move-calendar-to-top-of-page-maybe): Remove parens around planner-calendar-html-tag-marker. Thanks to Michael Boehlen for pointing this out and Paul D. Kraus for reminding me about it. modified files: ChangeLog planner-calendar.el 2005-06-30 06:17:53 GMT Sacha Chua patch-432 Summary: Bugfix: planner-edit-task-description, planner-deadline: keep point Revision: planner--dev--1.0--patch-432 * planner.el (planner-edit-task-description-basic): Keep cursor position. Remove the need for planner-multi advice. Thanks to Edgar Goncalves for pointing this out. * planner-multi.el (planner-multi-edit-task-description): Keep cursor position. Remove the need for planner-multi advice. * planner-deadline.el (planner-deadline-update): Be a lot more careful about the point to avoid infinite looping bugs or errors about task descriptions. * planner.el (planner-tasks-never-suppress-fixing-flag): Docfix: Explain what fixing is. Thanks to johnsu01 for pointing this out. modified files: ChangeLog planner-deadline.el planner-multi.el planner.el 2005-06-30 04:28:19 GMT Michael Olson patch-17 Summary: Fix planner-derived-mode-p issues around planner-save-buffers. Revision: planner-muse--mwolson--1.0--patch-17 * planner.el (muse): Thanks to Peter K. Lee for the patch! (planner-derived-mode-p): since calling derived-mode-p directly now instead of defalias, must have the &rest list unexpanded since derived-mode-p sees (list (list ...)) instead of (list ...). (planner-save-buffers): for some reason `muse-page-name' returns a "" whereas `emacs-wiki-page-name' returns nil. added an extra check for the muse case. modified files: ChangeLog.mwolson planner.el 2005-06-27 12:27:11 GMT Sacha Chua patch-431 Summary: planner-create-note: Default to current page Revision: planner--dev--1.0--patch-431 * planner.el (planner-create-note): Default to current page. Thanks to Scott Otterson for the suggestion. modified files: ChangeLog planner.el 2005-06-27 12:14:44 GMT Sacha Chua patch-430 Summary: planner-update-task: Remove need for advice, planner-multi-replan-task: Accept list as argument Revision: planner--dev--1.0--patch-430 * planner.el (planner-update-task-basic): Rename old planner-update-task to remove the need for advice. (planner-update-task): Alias to planner-update-task-basic. * planner-multi.el (planner-multi-replan-task): Accept lists. (planner-multi-update-task): Remove need for advice. (planner-update-task): Alias to planner-multi-update-task. (planner-multi-read-name): Use planner-make-link. (planner-multi-remove-task-from-pool): Take advantage of lists as argument for planner-multi-replan-task. modified files: ChangeLog planner-multi.el planner.el 2005-06-27 08:43:35 GMT Yann Hodique patch-12 Summary: doc improvement Revision: planner--yh--1.0--patch-12 more documentation modified files: ChangeLog.yh planner-xtla.el 2005-06-26 11:31:00 GMT Yann Hodique patch-11 Summary: publish xtla:// links with respect to archive locations Revision: planner--yh--1.0--patch-11 * planner-xtla.el (planner-xtla-url-transform-alist): associate branches with locations (planner-xtla-url-transform): build url from xtla link (muse-publish-url-transforms): add planner-xtla-url-transform to the list modified files: ChangeLog.yh planner-xtla.el 2005-06-25 06:32:48 GMT Michael Olson patch-9 Summary: Use `planner-current-file' to get around the temp file issue. Revision: planner--mwolson--1.0--patch-9 * planner.el (planner-current-file): New function that returns the name of the file that is currently being published. Make sure you use this instead of `buffer-file-name' if your routine is called at publish-time. For safety, this makes sure that `emacs-wiki-current-file' is bound and not null before using it; falls back on the value of the `buffer-file-name' variable. * planner-diary.el (planner-diary-get-name): Use `planner-current-file'. * planner-rss.el (planner-rss-limit): Ditto. modified files: planner-diary.el planner-rss.el planner.el 2005-06-25 05:33:19 GMT Michael Olson patch-8 Summary: Use `planner-match-string-no-properties'. Revision: planner--mwolson--1.0--patch-8 * planner.el (planner-match-string-no-properties): Use instead of `match-string-no-properties'. (planner-annotation-from-planner-note) (planner-task-info-from-string, planner-current-note-info) (planner-notes-get-headlines): Make use of this variable. * planner-appt.el (planner-appt-add-appts-from-schedule): Ditto. * planner-deadline.el (planner-deadline-get-deadline-from-string): Ditto. * planner-gnus.el (planner-gnus-get-address): Ditto. * planner-id.el (planner-id-get-id-from-string): Ditto. * planner-rank.el (planner-rank-get-task-info): Ditto. * planner-rdf.el (planner-rdf-get-taskid, planner-rdf-get-note-info) (planner-rdf-replace-links, planner-rdf-note-get-alias) (planner-rdf-note-get-plan, planner-rdf-note): Ditto. modified files: planner-appt.el planner-deadline.el planner-gnus.el planner-id.el planner-rank.el planner-rdf.el planner.el 2005-06-25 05:22:50 GMT Michael Olson patch-7 Summary: Use `planner-derived-mode-p' instead of `derived-mode-p'. Revision: planner--mwolson--1.0--patch-7 * planner.el (with-planner): Remove commented-out declare line since we're using the correct alternative. * planner-el.texi (Publishing): Use `planner-derived-mode-p' instead of `derived-mode-p'. * planner-report.el (planner-report-generate): Ditto. * planner.el (planner-read-task): Ditto. modified files: planner-el.texi planner-report.el planner.el 2005-06-25 05:02:34 GMT Michael Olson patch-6 Summary: Fix minor meaning change in `planner-report-find-tasks'. Revision: planner--mwolson--1.0--patch-6 * planner-report.el (planner-report-find-tasks): Re-add two dropped arguments. modified files: planner-report.el 2005-06-24 23:48:10 GMT Michael Olson patch-5 Summary: Put space in front of lists. Revision: planner--mwolson--1.0--patch-5 * planner.el (planner-notes-tag, planner-markup-task): Put space in front of lists for forward-compatibility with Muse. modified files: planner.el 2005-06-24 23:38:49 GMT Michael Olson patch-4 Summary: Use `planner-replace-regexp-in-string' for compat with Muse port. Revision: planner--mwolson--1.0--patch-4 * planner.el (planner-replace-regexp-in-string): Renamed from `planner-replace-in-string', since we use `planner-replace-regexp-in-string' in the Muse port. * planner-bbdb.el (planner-bbdb-annotation-from-bbdb): Use `planner-replace-regexp-in-string'. * planner-bibtex.el (planner-bibtex-annotation-old): Ditto. * planner-calendar.el (planner-calendar-published-file-href): Ditto. * planner-report.el (planner-report-find-notes) (planner-report-find-tasks): Ditto. * planner-timeclock-summary.el (planner-timeclock-summary-extract-task-data) (planner-timeclock-summary-make-summary-string-range) (planner-timeclock-summary-update, planner-timeclock-summary-show-range) (planner-timeclock-summary-show-2) (planner-timeclock-summary-generate-report): Ditto. modified files: planner-bbdb.el planner-bibtex.el planner-calendar.el planner-report.el planner-timeclock-summary.el planner.el 2005-06-24 22:11:36 GMT Michael Olson patch-3 Summary: Don't pollute the XEmacs namespace. Revision: planner--mwolson--1.0--patch-3 * planner-bibtex.el (planner-bibtex-key-in-head): New function that takes the place of `bibtex-key-in-head'. * planner-calendar.el: Remove definition of `replace-in-string'. * planner-timeclock-summary.el: Ditto. * planner.el (planner-derived-mode, planner-copy-overlay) (planner-remove-overlays, planner-link-escape, planner-link-unescape): Use defun instead of alias. * planner.el (planner-replace-in-string): New function the takes the place of `replace-in-string' and `replace-regexp-in-string'. * planner.el (planner-line-end-position, planner-line-beginning-position): New functions that take the place of `line-end-position' and `line-beginning-position', respectively. * planner-rank.el, planner-trunk.el, planner-calendar.el, planner-appt.el, planner-xtla.el, planner-multi.el, planner-report.el, planner-timeclock-summary.el, planner-mhe.el, planner-bbdb.el, planner-bibtex.el, planner-experimental.el, planner-id.el, planner.el, planner-tasks-overview.el, planner-el.texi, planner-ledger.el, planner-authz.el, planner-deadline.el: Replace uses of namespace-violating functions with the aforementioned ones. modified files: planner-appt.el planner-authz.el planner-bbdb.el planner-bibtex.el planner-calendar.el planner-deadline.el planner-el.texi planner-experimental.el planner-id.el planner-ledger.el planner-mhe.el planner-multi.el planner-rank.el planner-report.el planner-tasks-overview.el planner-timeclock-summary.el planner-trunk.el planner-xtla.el planner.el 2005-06-24 01:39:54 GMT Michael Olson patch-12 Summary: Uniquify publishing number for notes. Revision: planner-muse--mwolson--1.0--patch-12 * planner.el (muse-publish-markup-regexps): Use a different publishing number for notes, since these should probably not be the same. modified files: ChangeLog.mwolson planner.el 2005-06-23 16:32:27 GMT Sacha Chua patch-428 Summary: Bugfix: planner-annotation-as-kill: Make sure link is set Revision: planner--dev--1.0--patch-428 * planner.el (planner-annotation-as-kill): Make sure link is set before using it in link-name. Thanks to Jim Ottaway for catching this. modified files: ChangeLog planner.el 2005-06-23 14:47:10 GMT Jim Ottaway patch-75 Summary: planner-appt: remove redundant comments Revision: planner--jeho--1.0--patch-75 modified files: planner-appt.el 2005-06-23 11:49:42 GMT Jim Ottaway patch-74 Summary: planner-appt: fix duplicate appt bug Revision: planner--jeho--1.0--patch-74 * planner-appt.el (planner-appt-clear-appts): removed previous attempt at a fix (planner-appt-make-appt-element): new function for building elements of appt-time-msg-list (planner-appt-remember-appt): use planner-appt-make-appt-element (planner-appt-task-member): use planner-appt-make-appt-element modified files: planner-appt.el planner.el 2005-06-22 21:18:39 GMT Yann Hodique patch-7 Summary: fix note publishing Revision: planner--yh--1.0--patch-7 * planner.el (planner-markup-note): fix note publishing issue with muse (don't know exactly the reason though) modified files: ChangeLog.yh planner.el 2005-06-22 14:03:02 GMT Sacha Chua patch-427 Summary: Embarrassing typo: Missing ) Revision: planner--dev--1.0--patch-427 * planner-gnus.el (planner-gnus-browse-url): Fix another embarrassing typo. modified files: ChangeLog planner-gnus.el 2005-06-22 03:50:07 GMT Sacha Chua patch-426 Summary: Bugfix: with-planner-update-setup: Don't block planner-id Revision: planner--dev--1.0--patch-426 * planner.el (with-planner-update-setup): Don't block planner-id anymore. Trust that the equality code is working and that you won't get loops. * planner-id.el (planner-id-update-tasks-on-page): Nullify planner-id-update-automatically to avoid loops. modified files: ChangeLog planner-id.el planner.el 2005-06-22 03:43:37 GMT Sacha Chua patch-425 Summary: Bugfix: with-planner-update-setup, planner-browse-position-url, planner-multi-tasks-equal-p Revision: planner--dev--1.0--patch-425 * planner.el (with-planner-update-setup): Set planner-id-update-automatically to nil. (planner-save-buffers): Don't bind planner-id-update-automatically. (planner-browse-position-url): Correct typo. * planner-multi.el (planner-multi-tasks-equal-p): Bugfix: Correct equality test for tasks with only one plan page. modified files: ChangeLog planner-id.el planner-multi.el planner.el 2005-06-22 03:14:43 GMT Sacha Chua patch-424 Summary: Bugfix: planner-gnus-browse-url and long grou pnames Revision: planner--dev--1.0--patch-424 * planner-gnus.el (planner-gnus-browse-url): Merge patch from Toby Allsopp to fix case where gnus-registry-use-long-group-names is non-nil. modified files: ChangeLog planner-gnus.el 2005-06-21 16:23:33 GMT Sacha Chua patch-423 Summary: Bugfix: planner-browse-position-url: Do not clobber match data Revision: planner--dev--1.0--patch-423 * planner.el (planner-browse-position-url): Improve match data handling. Thanks to Romain Francoise for the patch. modified files: ChangeLog planner.el 2005-06-20 04:25:42 GMT Sacha Chua patch-422 Summary: Bugfix: planner-annotation-from-file-with-position: Check if buffer has a file Revision: planner--dev--1.0--patch-422 * planner.el (planner-annotation-from-file-with-position): Check if buffer is associated with a file. modified files: ChangeLog planner-id.el planner.el 2005-06-20 02:52:08 GMT Sacha Chua patch-421 Summary: New: planner-annotation-from-file-with-position Revision: planner--dev--1.0--patch-421 * planner.el (planner-resolve-position-url): New. (planner-browse-position-url): New. (planner-annotation-from-file-with-position): New. (planner-annotation-functions): Use planner-annotation-from-file-with-position instead of planner-annotation-from-file. modified files: ChangeLog planner.el 2005-06-19 04:24:51 GMT Michael Olson patch-10 Summary: Remove `muse-index-as-string' workaround. Revision: planner-muse--mwolson--1.0--patch-10 * planner.el (muse-index-as-string): Remove since we will have this functionality in the Muse 3.01 release. modified files: ChangeLog.mwolson planner.el 2005-06-18 16:35:34 GMT Yann Hodique patch-6 Summary: Provide a string representation of index to solve the index publishing issue Revision: planner--yh--1.0--patch-6 * planner.el (planner-index-as-string): Generates an index for planner in a string format. This solves the index publishing issue. If you want an index for your pages, just put something like (planner-index-as-string t t) somewhere in a page (muse-index-as-string): planner-index-as-string uses this new function, but it is not realeased as of version 3.0. Hack to be removed once muse integrates its own version of muse-index-as-string (planner-generate-index): make use of planner-index-as-string modified files: ChangeLog.yh planner.el 2005-06-18 01:03:49 GMT Sacha Chua patch-420 Summary: planner-annotation-as-kill: New interactive prefix Revision: planner--dev--1.0--patch-420 * planner.el (planner-annotation-as-kill): Merge patch from Stefan Reichör adding interactive prefix to planner-annotation-as-kill, allowing users to specify description. * planner-el.texi (Hyperlinks): New section documenting planner-annotation-as-kill. modified files: ChangeLog planner-el.texi planner.el 2005-06-17 15:31:23 GMT Sacha Chua patch-419 Summary: Docfix: Note that Lisp tags work only for GNU Emacs Revision: planner--dev--1.0--patch-419 * planner-diary.el: Docfix: Note that Lisp tags work only for GNU Emacs. Reverse order of recommendations. * planner-el.texi (Diary): Docfix: Note that Lisp tags work only for GNU Emacs. Reverse order of recommendations. modified files: ChangeLog planner-diary.el planner-el.texi 2005-06-17 08:45:31 GMT Sacha Chua patch-418 Summary: Enhancement: planner-multi-remove-task-from-pool works with multiple pages Revision: planner--dev--1.0--patch-418 * planner-multi.el (planner-multi-remove-task-from-pool): Work with multiple pages. (planner-multi-split): Gracefully deal with lists. (planner-multi-copy-tasks-to-page): Docfix: note multiple pages syntax. modified files: ChangeLog planner-el.texi planner-multi.el 2005-06-17 08:26:53 GMT Sacha Chua patch-417 Summary: planner-multi-copy-tasks-to-page: New option automatically copies tasks Revision: planner--dev--1.0--patch-417 * planner-multi.el (planner-multi-copy-tasks-to-page): New option allows you to automatically copy tasks to a page. (planner-multi-create-task-from-info): Convert from advice. (planner-create-task-from-info-function): Override with planner-multi version. (planner-multi-remove-task-from-pool): New hook function to remove copied tasks. * planner.el (planner-create-task-from-info-function): Change to variable. (planner-create-task-from-info): Call the function. (planner-create-task-from-info-basic): Rename from old function. * planner-el.texi (Multiple Projects): Document planner-multi.el. modified files: ChangeLog planner-el.texi planner-multi.el planner.el 2005-06-17 03:28:54 GMT Sacha Chua patch-416 Summary: planner-mark-task: Do everything inside with-planner-update-setup Revision: planner--dev--1.0--patch-416 * planner.el (planner-mark-task): Do everything inside with-planner-update-setup. (planner-tasks-never-suppress-fixing-flag): Default to t. (planner-mark-task-hook): Docfix: Add note about behavior and return value. (with-planner-update-setup): Nullify planner-tasks-file-behavior inside the macro. * planner-timeclock.el (planner-timeclock-task-marked): Return t following new planner-mark-task-hook. modified files: ChangeLog planner-timeclock.el planner.el 2005-06-16 05:57:33 GMT Sacha Chua patch-415 Summary: planner-multi: planner-task-plan: override for planner-multi Revision: planner--dev--1.0--patch-415 * planner-multi.el (planner-task-plan): Override this for planner-multi as well. modified files: ChangeLog planner-multi.el 2005-06-16 05:16:43 GMT Sacha Chua patch-414 Summary: Bugfix: planner-narrow-to-note should recognize more notes properly now Revision: planner--dev--1.0--patch-414 * planner.el (planner-narrow-to-note): Recognize notes even outside sections. modified files: ChangeLog planner.el 2005-06-16 04:51:37 GMT Sacha Chua patch-413 Summary: Bugfix: planner-current-note-info should work with notes with parens Revision: planner--dev--1.0--patch-413 * planner.el (planner-current-note-info): Bugfix: Work with notes with parens in titles. * planner-multi.el (planner-update-note): Go to the right file. modified files: ChangeLog planner-multi.el planner.el 2005-06-14 21:41:22 GMT Michael Olson patch-8 Summary: Supply ChangeLog files for each of the major players of the Muse port. Revision: planner-muse--mwolson--1.0--patch-8 * ChangeLog: Move to ChangeLog.mwolson. * ChangeLog.yh: File containing Yann Hodique's changes; it is autogenerated. * ChangeLog.sacha-muse: File containing Sacha Chua's planner--muse changes; it is autogenerated. new files: .arch-ids/ChangeLog.sacha-muse.id .arch-ids/ChangeLog.yh.id ChangeLog.sacha-muse ChangeLog.yh modified files: ChangeLog.mwolson renamed files: .arch-ids/ChangeLog.id ==> .arch-ids/ChangeLog.mwolson.id ChangeLog ==> ChangeLog.mwolson 2005-06-14 19:27:17 GMT Michael Olson patch-6 Summary: Patch from Peter K. Lee; make it less work to get started using this. Revision: planner-muse--mwolson--1.0--patch-6 * planner.el: Apply patch from Peter K. Lee. Require `muse-mode' instead of `muse'. (planner-option-customized): Since there are still a lot of functions that call this, keep it for now. (planner-page-exists-p): This is sometimes called with 2 arguments instead of 1, so defalias it to `planner-page-file'. * planner.el (planner-version): Change to "Planner (Muse)" so that this is somewhat meaningful. (planner-regexp-space): Make the default value equivalent to `muse-regexp-space'. (planner-update-wiki-project): Bring this back, but make it do nothing. I want to make the instructions on the PlannerMusePort wiki page a bit simpler. (planner-markup-tags): Ditto. modified files: ChangeLog planner.el 2005-06-13 02:20:27 GMT John Sullivan patch-13 Summary: Reorganization of More about Tasks node Revision: planner--johnsu01--0--patch-13 Reorganized the More about Tasks section into three subsections. Much more fine-tuning of the subsubsections to follow. The goal is to organize things conceptually rather than by module, while still making it easy to locate information pertaining to a particular module. modified files: planner-el.texi 2005-06-09 09:55:04 GMT Sacha Chua patch-411 Summary: New hook: planner-mark-task-hook Revision: planner--dev--1.0--patch-411 * planner.el (planner-mark-task-hook): New hook. (planner-mark-task): Use planner-mark-task-hook. * planner-timeclock.el (planner-timeclock-task-marked): Take advantage of new hook. (planner-task-in-progress): Remove separate advice. (planner-task-done): Remove separate advice. (planner-task-pending): Remove separate advice. modified files: ChangeLog planner-timeclock.el planner.el 2005-06-09 09:34:02 GMT Sacha Chua patch-409 Summary: Bugfix: Use write-file-hooks Revision: planner--dev--1.0--patch-409 * planner-appt.el (planner-appt-write-file-hook): Use write-file-hooks instead of local-write-file-hooks. Thanks to David Lord for pointing this out. * planner-id.el (planner-id-setup): Use write-file-hooks. * planner.el (planner-mode): Use write-file-hooks. * planner-accomplishments.el (planner-accomplishments-insinuate): Use write-file-hooks. modified files: ChangeLog planner-accomplishments.el planner-appt.el planner-id.el planner.el 2005-06-09 09:31:44 GMT Sacha Chua patch-408 Summary: planner-tasks-overview-get-summary: Work with files in subdirectories Revision: planner--dev--1.0--patch-408 * planner-tasks-overview.el (planner-tasks-overview-get-summary): Prefix command prompts for pages to display. Work with files in subdirectories. Unfortunately, this results in the function being much slower... * planner-el.texi (Task Overviews): Document planner-tasks-overview-get-summary. modified files: ChangeLog planner-el.texi planner-tasks-overview.el 2005-06-09 06:38:07 GMT Sacha Chua patch-406 Summary: Bugfix: planner-appt-add-appts-from-schedule and empty schedules Revision: planner--dev--1.0--patch-406 * planner-appt.el (planner-appt-add-appts-from-schedule): Merged bugfix from Jim for case where schedule is empty. modified files: ChangeLog planner-appt.el 2005-06-07 08:51:02 GMT Sacha Chua patch-405 Summary: Bugfix: Allow arbitrary extensions by using emacs-wiki-page-name Revision: planner--dev--1.0--patch-405 * planner.el (planner-get-current-date-filename): Allowed arbitrary extensions by using emacs-wiki-page-name instead of the buffer name. (planner-prepare-file): Ditto. (plan): Ditto. modified files: ChangeLog planner.el 2005-06-07 08:29:55 GMT Sacha Chua patch-404 Summary: Bugfix: planner-delete-note actually works now, and planner-rss recognizes categories Revision: planner--dev--1.0--patch-404 * planner.el (planner-delete-note): Bugfix: Saved excursion so that this will actually work. * planner-rss.el (planner-rss-add-item): Allow multiple categories. (planner-rss-add-note): Recognize multiple categories. modified files: ChangeLog planner-rss.el planner.el 2005-06-05 10:42:34 GMT Sacha Chua patch-403 Summary: New function: planner-delete-section[-text], add CREATE to planner-narrow-to-section Revision: planner--dev--1.0--patch-403 * planner-diary.el (planner-diary-delete-section): Deleted. (planner-diary-delete-section-text): Deleted. * planner.el (planner-delete-section): New function based on planner-diary-delete-section. Changed arguments from FILE TITLE to SECTION. * planner.el (planner-delete-section-text): New function based on planner-diary-delete-section. Changed arguments from FILE TITLE to SECTION. * planner.el (planner-narrow-to-section): New CREATE argument. * planner-el.texi (Other Interactive Functions): Document new CREATE argument. modified files: ChangeLog planner-diary.el planner-el.texi planner.el 2005-06-02 13:33:29 GMT Dryice Liu patch-42 Summary: Merge Andrew's change and support definde section access rule Revision: planner--dev--1.0--patch-42 * planner-authz.el: merge Andrew's change to make sure the perl code fit Mason format and more. (planner-authz-sections-rule-list): New customizable to define access rule. (planner-authz-publishing-markup-first): support access by section by default. (planner-authz-markup-section-predict): new helper function to check if the prediction is satisfied. (planner-authz-markup-section): new function to grant access permission according to planner-authz-sections-rule-list modified files: planner-authz.el 2005-06-02 11:07:46 GMT Sacha Chua patch-402 Summary: Provide planner-log-edit like functionality for xtla Revision: planner--dev--1.0--patch-402 * planner-xtla.el (planner-xtla-log-edit-add-note): Merge patch from Stefan Reichör providing planner-log-edit like functionality for xtla. modified files: ChangeLog planner-xtla.el 2005-05-28 12:44:54 GMT Sacha Chua patch-401 Summary: Docfix: planner-lisp: Add arbitrary functions example Revision: planner--dev--1.0--patch-401 * planner-el.texi (Interactive Lisp): Document arbitrary functions and provide an example. modified files: ChangeLog planner-el.texi 2005-05-28 12:18:46 GMT Sacha Chua patch-399 Summary: Bugfix: planner-extract-tasks: Accept list of pages Revision: planner--dev--1.0--patch-399 * planner.el (planner-extract-tasks): Accept list of pages as a parameter instead of requiring a subset of planner-file-alist. Thanks to Peter K. Lee for the patch. modified files: ChangeLog planner.el 2005-05-26 10:40:08 GMT Jim Ottaway patch-68 Summary: small change to planner-lisp.el Revision: planner--jeho--1.0--patch-68 * planner-lisp.el: If it looks like a lisp form, read and evaluate it; otherwise call it interactively as before. Corrected a small error in the documentation: [[lisp://plan... => [[lisp:/plan... modified files: planner-lisp.el 2005-05-22 06:02:41 GMT Michael Olson patch-5 Summary: Make generated lists publish correctly. Revision: planner-muse--mwolson--1.0--patch-5 * planner.el (planner-notes-tag, planner-markup-task): Print space before the dash when composing a list entry. modified files: ChangeLog planner.el 2005-05-22 03:24:30 GMT Sacha Chua patch-398 Summary: Docfix: planner-el.texi refers to wrong URL Revision: planner--dev--1.0--patch-398 * planner-el.texi (Getting Help): Fix wrong URL. Thanks to Neal McBurnett for pointing this out! modified files: ChangeLog planner-el.texi 2005-05-22 01:00:43 GMT Michael Olson patch-4 Summary: Cause task IDs to be colored. Revision: planner-muse--mwolson--1.0--patch-4 * planner-id.el (planner-id-setup): Since we append values to `muse-colors-buffer-hook' in the `planner-setup-highlighting' function, do so here as well. Otherwise `planner-id-markup' never gets called. I think the `run-hook-with-args' function in Emacs CVS may have a bug. * planner-appt.el (planner-appt-font-setup): Ditto. modified files: ChangeLog planner-appt.el planner-id.el 2005-05-21 04:54:07 GMT Michael Olson patch-3 Summary: Merge massively from sacha/367 to sacha/396, with some omissions. Revision: planner-muse--mwolson--1.0--patch-3 I ran "tla changes emacs-wiki--dev--1.0--patch-366" while in the directory containing the emacs-wiki--dev--1.0 tree so that I could get a cumulative patch of all the changes from patch-366 to the present. I merged in as much as I could. It seemed that the file permissions changed to 644 recently for files in the planner archive, so I followed suit. It is hoped that this effort will help Sacha keep the Muse port of Planner current :^) . I haven't yet tested these changes; I should do that soon. modified files: ChangeLog planner-appt.el planner-bookmark.el planner-diary.el planner-el.texi planner-gnus.el planner-id.el planner-multi.el planner-rank.el planner-timeclock-summary-proj.el planner-timeclock-summary.el planner-timeclock.el planner-trunk.el planner-vm.el planner.el {arch}/emacs-wiki/emacs-wiki--sacha/emacs-wiki--sacha--1.0/sacha@free.net.ph--main/patch-log/patch-5 2005-05-17 21:34:27 GMT John Sullivan patch-10 Summary: Fixes to Appointments node Revision: planner--johnsu01--0--patch-10 Added missing @item's to @itemize list. modified files: planner-el.texi 2005-05-12 10:21:55 GMT Sacha Chua patch-397 Summary: planner-bibtex-regexp: Fix typo. Revision: planner--dev--1.0--patch-397 * planner-bibtex.el (planner-bibtex-regexp): Fix typo. Thanks to Wei-Hao Lin for the patch. modified files: ChangeLog planner-bibtex.el 2005-05-12 06:01:31 GMT John Sullivan patch-8 Summary: Fixed typo. Revision: planner--johnsu01--0--patch-8 Typo in Using Allout Mode. modified files: planner-el.texi 2005-05-12 02:06:55 GMT John Sullivan patch-7 Summary: Catch up, add content to docs. Revision: planner--johnsu01--0--patch-7 Added Sacha's tip about using Allout mode with notes. modified files: planner-el.texi 2005-05-09 10:34:45 GMT Sacha Chua patch-396 Summary: NOTE: planner-tasks-file-behavior new default: 'close Revision: planner--dev--1.0--patch-396 * planner.el (planner-tasks-file-behavior): Set the default to 'close. Thanks to Sharon Kimble for making me realize that this is the reasonable default. modified files: ChangeLog planner.el 2005-05-07 14:19:21 GMT Sacha Chua patch-395 Summary: planner-list-tasks-with-status bugfix: Deal with undated tasks; do not touch planner-task-format Revision: planner--dev--1.0--patch-395 * planner.el (planner-list-tasks-with-status): Use planner-task-page instead of date to deal with undated tasks. Do not use planner-task-format. Thanks to sf for pointing these out. * planner-el.texi (Viewing Tasks): Update documentation for planner-list-unfinished-tasks to reflect new argument PAGES. modified files: ChangeLog planner-el.texi planner.el 2005-05-06 03:58:31 GMT Sacha Chua patch-394 Summary: planner-list-unfinished-tasks: Add PAGES argument Revision: planner--dev--1.0--patch-394 * planner.el (planner-list-unfinished-tasks): Add PAGES argument. Same semantics as planner-list-tasks-with-status. modified files: ChangeLog planner.el 2005-05-06 03:52:37 GMT Sacha Chua patch-393 Summary: planner-list-tasks-with-status: Put an insane amount of meaning into a PAGES argument Revision: planner--dev--1.0--patch-393 * planner.el (planner-file-alist): Filter using PAGES. (planner-list-tasks-with-status): NOTE: Change argument from START and END to PAGES to allow much greater flexibility. This function is now way too smart about PAGES. * planner-el.texi (Viewing Tasks): Update planner-list-tasks-with-status again. modified files: ChangeLog planner-el.texi planner.el 2005-05-06 03:08:32 GMT Sacha Chua patch-392 Summary: planner-list-tasks-with-status: Fix insert-file-contents(nil) backtrace Revision: planner--dev--1.0--patch-392 * planner.el (planner-tasks-tag): Do not include temporary files. (planner-search-notes-internal): Do not include temporary files. (planner-past-notes-tag): Do not include temporary files. (planner-list-tasks-with-status): Do not include temporary files. Do not insert template. Add new arguments START and END. Thanks to sf for reporting this bug. This should fix the case where unsaved files cause a backtrace starting with insert-file-contents(nil). * planner-el.texi (Viewing Tasks): Update docuentation for planner-list-tasks-with-status. modified files: ChangeLog planner-el.texi planner.el 2005-04-28 03:55:29 GMT Sacha Chua patch-390 Summary: Bugfix: planner-sort-tasks: Remove non-fontification code Revision: planner--dev--1.0--patch-390 * planner.el (planner-sort-tasks): Remove buggy non-fontification code again. Thanks to sf for pointing this out. modified files: ChangeLog planner.el 2005-04-27 18:50:52 GMT Sacha Chua patch-389 Summary: Bugfix: planner-sort-tasks should use 5-arg sort-subr for older GNU Emacs Revision: planner--dev--1.0--patch-389 * planner.el (planner-sort-tasks): Guard against old GNU Emacs with 5 arguments instead of 6. Thanks to sf for reporting the bug. modified files: ChangeLog planner.el 2005-04-27 03:16:25 GMT Sacha Chua patch-388 Summary: Tweak: planner-copy-or-move-region does not include last line if at start of line Revision: planner--dev--1.0--patch-388 * planner.el (planner-copy-or-move-region): Minor tweak: Do not include last line if point is at the first character of the task. This makes selecting a region of tasks easier, and corresponds better to transient-mark-mode. modified files: ChangeLog planner.el 2005-04-27 03:13:30 GMT Sacha Chua patch-387 Summary: Bugfix: planner-gnus-browse-url: Load group even if registry is not used Revision: planner--dev--1.0--patch-387 * planner-gnus.el (planner-gnus-browse-url): Fix group loading code when registry is not used. modified files: ChangeLog planner-gnus.el 2005-04-27 03:07:15 GMT Sacha Chua patch-386 Summary: Bugfix: planner-replan-note should properly add notes to non-wiki-named pages Revision: planner--dev--1.0--patch-386 * planner.el (planner-replan-note): Bugfix: Go back to beginning of buffer whenever searching for a note. Also, get the base of the note page link when concatenating a new reference to it. This means that links specified with [[ and ]] should work. * planner-multi.el (planner-replan-note): Add current link only if it is not already in the list. Also, get the base of the note page link when concatenating a new reference to it. modified files: ChangeLog planner-multi.el planner.el 2005-04-26 14:40:11 GMT Sacha Chua patch-385 Summary: Bugfix: Make planner-sort-tasks stop causing backtraces Revision: planner--dev--1.0--patch-385 * planner.el (planner-sort-tasks): Merge Angus Lees' version fixing fontification-related backtrace by using sort-subr instead of sort-fields-1. modified files: ChangeLog planner.el 2005-04-26 12:29:33 GMT Jim Ottaway patch-64 Summary: planner-el.texi: updated planner-appt node Revision: planner--jeho--1.0--patch-64 Added documentation for new appointments section feature. Changed headings in the planner-appt node formatted with visual markup [@noindent..@strong{foo}] to @unnumberedsubsubsec. modified files: planner-el.texi 2005-04-23 17:06:25 GMT Jim Ottaway patch-63 Summary: merge latest; planner-appt changes Revision: planner--jeho--1.0--patch-63 * planner-appt.el: Summary: New functionality: task appointments may be copied into an appointments section. Documentation for new appointments section feature. Appointment text now has its task-id removed. (planner-appt-task-appointments-section, planner-appt-task-use-appointments-section-flag, planner-appt-format-appt-section-line-function): Customizable variables for appointment section (--planner-appt-tasks-added-appts, --planner-appt-tasks-earlier-appts): Moved up the file (planner-appt-forget-appt): New function (planner-appt-remove-task-id): New function: removes task-ids (planner-appt-format-description): New function to do all formatting of the appt description (planner-appt-task-member): Now requires a list as third argument. I wanted this to be an optional argument, but that didn't work because the list could be null. (planner-appt-format-appt-section-line, planner-appt-update-appt-section, planner-appt-update-appt-section-maybe): New functions: the basis of the task appointment section business. (with-planner-appt-update-section-disabled): Macro to temporarily switch of updating. (planner-appt-task-add): Now returns t if an appointment was actually added; use planner-appt-format-description; added some code supporting the task appointment section. (planner-appt-task-delete): Use planner-appt-format-description; added some code supporting the task appointment section. (planner-appt-add-appts-from-tasks): Support for task appointment section (planner-id-update-tasks-on-page): Support for task appointment section: do update afterwards. (planner-appt-add-appts-from-schedule): Support for task appointment section; check that the line looked at didn't come from the task list. modified files: ChangeLog planner-appt.el 2005-04-22 04:50:36 GMT Sacha Chua patch-384 Summary: Improve support for putting files in subdirectories Revision: planner--dev--1.0--patch-384 * planner.el (planner-list-daily-files): List daily files in subdirectories as well. Thanks to Wei-Hao Lin for pointing this out. (planner-extract-tasks): Use filenames from planner-file-alist. (planner-search-notes-internal): Use filenames from planner-file-alist. (planner-past-notes-tag): Use planner-get-day-pages and planner-file-alist. modified files: ChangeLog planner.el 2005-04-21 04:54:01 GMT Sacha Chua patch-383 Summary: planner-multi-read-name-multiple-prompts: Easier multiple inputs with nil default Revision: planner--dev--1.0--patch-383 * planner-multi.el (planner-multi-read-name-multiple-prompts): Make the default nil to improve ease of entering multiple pages under XEmacs. Also, save the completed list as the default page. modified files: ChangeLog planner-multi.el 2005-04-20 17:40:35 GMT Sacha Chua patch-382 Summary: XEmacs compatibility: condition-case instead of 4-arg require, XEmacs menu strangeness Revision: planner--dev--1.0--patch-382 * planner-multi.el (err): Replace with XEmacs-friendly version that uses condition-case to catch require errors. Thanks to Andreas Stemmer for the bug report and Jim Ottaway for the suggested fix. * planner-timeclock.el (nil): Hackish workaround for XEmacs menu strangeness. Despite being mentioned in easy-menu-add-item's docstring, easy-menu-create-menu does not exist in XEmacs. * planner-bookmark.el (bookmark-set): Replace 4-arg require with condition-case. modified files: ChangeLog planner-bookmark.el planner-multi.el planner-timeclock.el 2005-04-20 09:11:00 GMT Sacha Chua patch-381 Summary: planner-vm: Turn on annotations in vm-presentation-mode as well Revision: planner--dev--1.0--patch-381 * planner-vm.el (planner-vm-annotation-from-mail): Turn on annotations in vm-presentation-mode as well. Thanks to Fran Burstall for the patch. modified files: ChangeLog planner-vm.el 2005-04-20 07:39:51 GMT Sacha Chua patch-380 Summary: Bugfix: planner-multi-replan-task, replace mapc with mapcar Revision: planner--dev--1.0--patch-380 * planner-multi.el (planner-multi-replan-task): Replace mapc with mapcar for Emacs20 compatibility. modified files: ChangeLog planner-multi.el 2005-04-20 07:20:03 GMT Sacha Chua patch-379 Summary: Document planner-trunk.el Revision: planner--dev--1.0--patch-379 * planner-el.texi (Grouping Tasks): Document planner-trunk. * planner-trunk.el (planner-trunk-rule-list): Put in the actual regular expression. to make it less intimidating. Rewrite the custom rules to be more helpful. modified files: ChangeLog planner-el.texi planner-trunk.el 2005-04-19 14:40:47 GMT Sacha Chua patch-378 Summary: Merge planner-appt updates from jeho: create task fix, better advising Revision: planner--dev--1.0--patch-378 * planner.el (planner-live-task-regexp): Rename from planner-appt-live-task-regexp. * planner-id.el (planner-id-update-tasks-on-page): Use planner-live-task-regexp. (planner-id-remove-tasks-on-page): Use planner-task-regexp. (planner-id-add-task-id-to-all): Use planner-task-regexp. * planner-appt.el: Remove planner-appt-live-task-regexp. (planner-appt-add-appts-from-tasks): Use planner-live-task-regexp. modified files: ChangeLog planner-appt.el planner-id.el planner.el 2005-04-19 14:18:11 GMT Jim Ottaway patch-62 Summary: with-planner-update-setup Revision: planner--jeho--1.0--patch-62 * planner.el (with-planner-update-setup): return value from the body modified files: planner.el 2005-04-19 11:47:33 GMT Yann Hodique patch-1 Summary: Some hacks on planner--muse Revision: planner--yh--1.0--patch-1 * planner-gnus.el: quote planner-gnus-browse-url * planner-log-edit.el (planner-log-edit-flush-regexp-list): add the possibility to ignore patterns before inserting commit messages as notes (useful for psvn) (planner-log-edit-add-note): use planner-log-edit-flush-regexp-list * planner-mhe.el ("mhe"): quote planner-mhe-browse-url * planner-unix-mail.el (planner-unix-mail-protocol-name): quote planner-unix-mail-protocol-name * planner.el (planner-annotation-format-local-file-name): add the possibility to format local file links (I use it to force files under my home dir to be displayed as ~/..., so that I can move my planner files easily between home and work) (planner-annotation-from-file): use planner-annotation-format-local-file-name (planner-annotation-from-dir): new annotation for handling dired buffers (planner-annotation-functions): use planner-annotation-from-dir modified files: planner-gnus.el planner-log-edit.el planner-mhe.el planner-unix-mail.el planner.el 2005-04-18 14:07:50 GMT Sacha Chua patch-377 Summary: planner-gnus: Pick up the group name properly Revision: planner--dev--1.0--patch-377 * planner-gnus.el (planner-gnus-browse-url): Pick up the group name properly. Thanks to Stefan Reichör for the patch! (planner-gnus-group-threshold): New. Might help with planner-gnus-browse-url and large groups. modified files: ChangeLog planner-gnus.el 2005-04-18 13:41:27 GMT Sacha Chua patch-376 Summary: planner-id bugfix (completed/cancelled tasks) and planner-el docfixes Revision: planner--dev--1.0--patch-376 * planner-id.el (planner-id-update-tasks-on-page): Fix cyclic saving caused when planner-id updates completed bugs even if force is nil. Thanks to SAITO Fuyuki for spotting the bug and suggesting a fix. * planner-el.texi: Change @var to @code whenever it referred to a program variable instead of a metasyntactic variable. modified files: ChangeLog planner-el.texi planner-id.el 2005-04-18 06:49:41 GMT John Sullivan patch-3 Summary: planner-el.texi (Diary): Corrected instructions for showing diary entries for multiple days. Replaced @code's with @var where appropriate. Revision: planner--johnsu01--0--patch-3 Keywords: modified files: planner-el.texi 2005-04-16 06:55:03 GMT John Sullivan patch-2 Summary: Replaced all occurrences of PlannerMode with Planner except where inaccurate. Revision: planner--johnsu01--0--patch-2 2005-04-16 06:53:23 GMT John Sullivan patch-1 Summary: Revision: planner--johnsu01--0--patch-1 modified files: planner-el.texi 2005-04-15 17:07:46 GMT Jim Ottaway patch-60 Summary: planner-appt: create task fix, better advising, etc. Revision: planner--jeho--1.0--patch-60 * planner-appt.el Quite a few changes here: Fixed a bug in task creation with multi links: previously, there would either be an error [if the task ends up added to an empty page] or the wrong task line would be considered for appointment adding [these problems due to idiosyncrasies in planner-multi]. Debugging macros and functions. Better advising: while investigating the task creation bug, I found that there were many redundant calls to the function advice, so I have added code temporarily to switch the advice off. I also noticed that the advice to `planner-update-task' couldn't possibly do anything useful before, since the current task line is unaffected by `planner-update-task', but that some advice was called for; so I added something here. This, however, turned out to be far too slow for the mass updating done by `planner-id-update-tasks-on-page', so I added some advice for that too. There are also improvements to the advising itself [preactivation and avoiding using ad-foo-regexp], with some speed gains. (planner-appt-live-task-regexp): fixed matching just whitespace after the task status (planner-appt-debug-buffer, planner-appt-debug-flag) (planner-appt-debug, planner-appt-debug-message): new debugging functionality (--planner-appt-task-cache, planner-appt-task-parse-task): added memoizing optimization (planner-schedule-task-estimate): added a docstring (planner-appt-task-add, planner-appt-task-delete): re-organized to make more efficient and more readable (--planner-appt-advice, planner-appt-advice-common-flags): support for new advising stuff; `--planner-appt-advice' holds information about advice added by `planner-appt-defadvice', `planner-appt-advice-common-flags' flags that are used in all advice. Preactivation of advice added here for load-time efficiency (planner-appt-defadvice): defadvice macro wrapper that remembers the advice args for later use (planner-appt-disable-all-advice, planner-appt-enable-all-advice): new functions: enable/disable all advice added with `planner-appt-defadvice' (with-planner-appt-task-advice-disabled): temporary disabling of advice added with `planner-appt-defadvice' (planner-task-cancelled, planner-task-done, planner-delete-task): now use `planner-appt-defadvice' (planner-appt-get-diff-links, planner-update-task): enhanced handling of `planner-update-task': previous code didn't actually do anything (planner-id-update-tasks-on-page): for speed, advised to avoid lots of update advice (plan): replaced the setq with a let clause (planner-copy-or-move-task): disable planner-appt advice while this advice is active; fixed bug in handling of planner-multi dates (planner-edit-task-description): use `planner-appt-defadvice' (--planner-appt-created-task-marker): support for create task advice (--planner-appt-close-the-buffer-flag): support for create task advice (planner-appt-create-task-hook-func): remember the place where the task was created, so it can be revisited to update appointments (planner-create-task-from-info): visit the place where the task was created, update appointments, and behave according to `planner-tasks-file-behavior' (planner-appt-methods): moved up the file to avoid byte-compilation warning (planner-appt-use): change function added to `planner-create-task-hook' to `planner-appt-create-task-hook-func'; moved the advice enabling to the end of the function [so advice can be explicitly disabled if the task method is not used [otherwise there is a problem with preactivation]] (planner-appt-de-insinuate): updated to take changes to hooks and advice handling into account modified files: planner-appt.el 2005-04-12 16:37:14 GMT Sacha Chua patch-375 Summary: Docfix: carrying over unfinished tasks. Revision: planner--dev--1.0--patch-375 * planner.el (plan): Update docstring for FORCE-DAYS. * planner-el.texi (Carrying Over Unfinished Tasks): Rewrite to reflect semantics of plan and planner-carry-tasks-forward. modified files: ChangeLog planner-el.texi planner.el 2005-04-10 14:26:53 GMT Sacha Chua patch-374 Summary: Docfix: Update URL for remind Revision: planner--dev--1.0--patch-374 * planner.el: Update URL for remind. Thanks to Sharon Kimble for pointing this out. modified files: ChangeLog planner.el 2005-04-08 08:16:23 GMT Sacha Chua patch-373 Summary: planner-psvn bugfix: stray paren Revision: planner--dev--1.0--patch-373 * planner-el.texi (Acknowledgements): Thanks to Stefan for planner-xtla. * planner-psvn.el (planner-psvn-log-edit-add-note): Fix stray paren. (Where did that come from?) Thanks to Stefan for spotting this. modified files: ChangeLog planner-el.texi planner-psvn.el 2005-04-07 15:27:26 GMT Sacha Chua patch-372 Summary: Bugfix: planner-vm-browse-url Revision: planner--dev--1.0--patch-372 * planner-vm.el (planner-vm-browse-url): Merge message-id bugfix from Greg Novak. modified files: ChangeLog planner-vm.el 2005-04-07 15:15:00 GMT Sacha Chua patch-371 Summary: New: planner-annotation-from-dired, planner-psvn Revision: planner--dev--1.0--patch-371 * planner.el (planner-annotation-from-dired): New from Stefan Reichör. (planner-annotation-functions): Add planner-annotation-from-dired. * planner-psvn.el: New from Stefan Reichör. * planner-el.texi (Acknowledgements): Add note about planner-psvn. new files: .arch-ids/planner-psvn.el.id planner-psvn.el modified files: ChangeLog planner-el.texi planner.el 2005-04-07 09:27:19 GMT Sacha Chua patch-370 Summary: New: planner-timewarp. Bugfix: Group .*? regexp to deal with possible XEmacs bug. Revision: planner--dev--1.0--patch-370 * planner.el (planner-timewarp): New. Thanks to Raymond Zeitler for the idea. (planner-timewarp-date): New. (planner-today): Pay attention to timewarp. (planner-expand-name): Pay attention to timewarp. * planner-appt.el (planner-appt-de-wiki): Group .*? regexp to deal with possible XEmacs bug. * planner-timeclock-summary.el (planner-timeclock-summary-extract-task-data): Group .*? regexp. modified files: ChangeLog planner-appt.el planner-timeclock-summary.el planner.el 2005-04-07 03:52:40 GMT Sacha Chua patch-369 Summary: Bugfix: planner-timeclock-summary-proj. New: planner-annotation-symbol-string, planner-create-task-from-note Revision: planner--dev--1.0--patch-369 * planner.el (planner-create-task-from-note): New. Thanks to Paul Lussier for suggesting this. (planner-create-task-from-buffer): Move task prompts into another function for ease of use. (planner-read-task): Prompt for task information. (planner-menu): Add planner-create-task-from-note and planner-create-note-from-task to menu. * planner.el (planner-create-task-from-buffer): Modify ddliu's annotation code to automatically add annotation at end of string if annotation string is not found. This means that you don't have to manually add the annotation anchor for most cases (annotation desired), although it also means that you can't disable annotation on a per-task basis. You can use planner-create-task if you don't want annotations. (planner-annotation-symbol-string): Make this the only variable controlling annotation; delete planner-manual-place-annotation, defaulting to {} (on) which is similar to the syntax of the "find" tool. * planner-rank.el (planner-rank-update-current-task): Remove need for progn. * planner-el.texi (Sacha Chua's Configuration): Merge johnsu01's docfixes escaping characters. * planner-timeclock-summary-proj.el (planner-timeclock-summary-proj): Fix provide statement. modified files: ChangeLog planner-bookmark.el planner-diary.el planner-el.texi planner-rank.el planner-timeclock-summary-proj.el planner.el 2005-04-07 01:46:32 GMT Dryice Liu patch-38 Summary: fix private symbal introduced yesterday Revision: planner--dev--1.0--patch-38 * planner.el (planner-create-task-from-buffer): Fix the private ddliu-planner-annotation-symbol-string I blindly copied from my config file yesterday. It should be planner-annotation-symbol-string. I should test it more. modified files: planner.el 2005-04-06 09:37:08 GMT Dryice Liu patch-37 Summary: Place the annotation in task title where I want Revision: planner--dev--1.0--patch-37 * planner.el: Sometimes I want to place the annotation in the task description instead of at the end of task description to get a more readable one. This patch makes this possible. (planner-manual-place-annotation): If set to non-nil, decide where annotation goes manually. It is set to nil by default to keep the original behavior. (planner-annotation-symbol-string): When planner-create-task-from-buffer, this string in the task description will be replace by the annotation calculated by planner-annotation-functions. (planner-create-task-from-buffer): Utilize planner-manual-place-annotation and planner-annotation-symbol-string so I can type "reply /anno/ for something" in Gnus and so on to get a better task title. modified files: planner.el 2005-04-06 08:40:21 GMT Dryice Liu patch-36 Summary: conditional require remember.el Revision: planner--dev--1.0--patch-36 * planner-bookmark.el: remove global require of remember (bookmark-set): require remember only if planner-bookmark-take-note-after-set-bookmark-flag is set tot. modified files: planner-bookmark.el 2005-04-06 08:16:26 GMT Dryice Liu patch-35 Summary: speed up planner-rank Revision: planner--dev--1.0--patch-35 * planner-rank.el (planner-rank-update-current-task): only run planner-rank-change when needed, i.e, urgency changed. (planner-rank-update-all): only search in the tasks section. modified files: planner-rank.el 2005-04-05 15:28:45 GMT Sacha Chua patch-367 Summary: Always add menu to planner-mode buffers Revision: planner--dev--1.0--patch-367 * planner.el (planner-mode): Always add menu. Thanks to Surendra Singhi for the suggestion. modified files: ChangeLog planner.el 2005-04-05 20:58:26 GMT Jim Ottaway patch-58 Summary: fixed fix of planner-multi-read-name Revision: planner--jeho--1.0--patch-58 * planner-multi.el (planner-multi-read-name): used simpler and neater method of modifying minibuffer-prompt-properties modified files: planner-multi.el 2005-04-05 06:48:58 GMT Sacha Chua patch-6 Summary: More twiddling Revision: planner--muse--1.0--patch-6 modified files: planner-appt.el planner-bbdb.el planner-bibtex.el planner-calendar.el planner-erc.el planner-experimental.el planner-gnus.el planner-id.el planner-mhe.el planner-multi.el planner-notes-index.el planner-rmail.el planner-tasks-overview.el planner-timeclock-summary.el planner-timeclock.el planner-unix-mail.el planner-vm.el planner.el 2005-04-05 05:34:42 GMT Sacha Chua patch-5 Summary: Generates indices Revision: planner--muse--1.0--patch-5 modified files: planner.el 2005-04-05 05:20:31 GMT Sacha Chua patch-4 Summary: planner-list-tasks-with-status now works. Revision: planner--muse--1.0--patch-4 modified files: planner.el 2005-04-05 05:07:14 GMT Sacha Chua patch-3 Summary: planner-delete-task now works. Revision: planner--muse--1.0--patch-3 modified files: planner.el 2005-04-05 05:05:06 GMT Sacha Chua patch-2 Summary: Plan pages highlight upon opening Revision: planner--muse--1.0--patch-2 modified files: planner.el 2005-04-05 04:48:32 GMT Sacha Chua patch-1 Summary: M-x plan works Revision: planner--muse--1.0--patch-1 * planner.el: Add requires for muse. (planner-project): Change docstring. (planner-mode): Derive from muse-mode. (planner-link-base): Copy code. (planner-encode-url): Copy code. (planner-mode-map): Make sparse keymap instead of copying. (planner-unhighlight-region): Promote from defadvice. (with-planner): Change with-planner. Use Muse equivalents for many functions. DELETED: - planner-update-wiki-project - planner-directory - planner-publishing-directory - planner-project-default-name - planner-emacs-wiki - planner-name-regexp - planner-custom-variables - planner-publishing-markup - planner-markup-tags modified files: planner.el 2005-04-05 01:43:34 GMT Sacha Chua patch-366 Summary: Bugfix: planner-multi read-only prompt, planner-sort-tasks excursions, planner-appt advice Revision: planner--dev--1.0--patch-366 * planner-multi.el (planner-multi-remprop): Remove cl dependency from planner-multi patch from jeho. * planner.el (planner-sort-tasks): Merge patch from Angus Lees removing unnecessary save-excursion. modified files: ChangeLog planner-appt.el planner-multi.el planner.el 2005-04-05 01:29:40 GMT Sacha Chua patch-365 Summary: planner-el.texi: Update my sample configuration file Revision: planner--dev--1.0--patch-365 * planner-el.texi (Sacha Chua's Configuration): Update my sample configration file. modified files: ChangeLog planner-el.texi 2005-04-04 20:59:00 GMT Jim Ottaway patch-56 Summary: planner-multi minibuffer properties fix Revision: planner--jeho--1.0--patch-56 * planner-multi.el (planner-multi-remprop): function to remove a property from a property list (planner-multi-read-name): bind minibuffer-prompt-properties sans read-only locally top-level: remove rebinding of minibuffer-prompt-properties modified files: planner-multi.el 2005-04-03 17:39:18 GMT Sacha Chua patch-364 Summary: planner-replan-task: Preserve initial task location as much as possible; fix planner-multi as well Revision: planner--dev--1.0--patch-364 * planner-multi.el (planner-multi-replan-task): Extensive debugging and testing. Converted from defadvice version and fixed. * planner.el (planner-replan-task-function): New variable. (planner-replan-task): Call the function. (planner-replan-task-basic): Tweak to preserve place. modified files: ChangeLog planner-multi.el planner.el 2005-04-01 23:48:06 GMT Sacha Chua patch-363 Summary: Merge docfixes from johnsu01 Revision: planner--dev--1.0--patch-363 2005-03-23 johnsu01 * planner-el.texi (Top): Added descriptions to some menu items. (Managing Your Information): Added descriptions to menu items. (Task Ranks): Incorporated patch-339 (Task Ranks): Incorporated patch-341. (Acknowledgements): Incorporated patch-351. 2005-03-14 johnsu01 * planner-el.texi (Log Edit): Added cindex entries in parallel with other sections (Logs and Version Control): Added cindex entries in parallel with other sections. (Schedule): Changed and added @cindex entries in parallel form with other sections. (Emacs Relay Chat): Added @cindex entries for IRC, and for expansion of both ERC and IRC. (Finances): Added @cindex. (Ledger): Added @cindex. (Contacts): Changed name to Contacts and Conversations, updated all relevant references. Added @cindex entries. (Appointments): Added @cindex. (Task-based Appointments): Added @cindex. (Task-based Appointments): Fixed @pxref formatting. (Schedule-based Appointments): Added @cindex entries. (Appt Notes): Added @cindex entries. (Gnus): Changed @ref to @inforef. (Schedule.el): Changed subsection title to be schedule.el. (Schedule.el): Changed node name to be schedule.el (More about Tasks): Added reference to other schedule.el section. (Rmail): Changed ref to inforef (Bookmark): Added inforef to Emacs manual Bookmarks section. 2005-03-11 johnsu01 * planner-el.texi: Reorganized "Integrating with Emacs" section into smaller sections formed by some common categories used in personal information management. Corrected the name of the info file in the section on how to install the info file. (Ledger) Made the planner-ledger @cindex entry use the same form as the other @cindex entries for modules. (Unix mail): Removed erroneous Rmail @cindex entry in this section. modified files: ChangeLog planner-el.texi 2005-04-01 06:48:33 GMT Sacha Chua patch-362 Summary: planner-multi: planner-copy-or-move-task: Unschedule tasks properly even if the date is escaped Revision: planner--dev--1.0--patch-362 * planner-multi.el (planner-task-date): Find dates properly even if escaped. (planner-copy-or-move-task): Delete dates properly even if escaped. modified files: ChangeLog planner-multi.el 2005-04-01 06:36:41 GMT Sacha Chua patch-361 Summary: planner-id-find-task bugfix: Stop at first task found Revision: planner--dev--1.0--patch-361 * planner-id.el (planner-id-find-task): Fix bug where task ID appears in notes as well. Thanks to Michael Heinrich for pointing this out. modified files: ChangeLog planner-id.el 2005-03-31 03:42:16 GMT Sacha Chua patch-360 Summary: planner-expand-name: Fix day offset Revision: planner--dev--1.0--patch-360 * planner.el: Rearrange some declarations to reduce compilation warnings. (planner-expand-name): Fix day offset again. Test within one week to make sure it makes sense. modified files: ChangeLog planner.el 2005-03-30 11:30:56 GMT Sacha Chua patch-359 Summary: planner-multi: planner-replan-note: properly cross-reference single-page entries Revision: planner--dev--1.0--patch-359 * planner-multi.el (planner-replan-note): Keep track of old date so that notes can be properly cross-referenced. This should make remember-planner work better with planner-multi. Thanks to Raymond Zeitler for complaining. =) modified files: ChangeLog planner-multi.el 2005-03-30 10:28:57 GMT Sacha Chua patch-358 Summary: planner-multi: Sane completing read in XEmacs Revision: planner--dev--1.0--patch-358 * planner-multi.el (nil): crm is optional. (planner-multi-read-name): Replace defadvice with more flexible way to define planner-multi prompting. This makes it work better under XEmacs because users can choose the next function instead. (planner-multi-read-name-multiple-prompts): New function for XEmacs users. Thanks to Jody Klymak for the idea. * planner.el (planner-read-name-function): New variable removes the need for defadvice in planner-multi. (planner-read-name-single): Contains old code for prompting for a single page. (planner-read-name-no-completion): Just in case people like it that way. modified files: ChangeLog planner-multi.el planner.el 2005-03-30 09:15:45 GMT Sacha Chua patch-357 Summary: planner-read-date: save and restore calendar mode map Revision: planner--dev--1.0--patch-357 * planner.el (planner-read-date): Save and restore calendar mode map. This should fix the bug reported by Pascal Quesseveur; dates should be selectable even when calendar-setup is non-nil. modified files: ChangeLog PLANNER-README planner.el 2005-03-30 04:01:26 GMT Sacha Chua patch-356 Summary: planner-multi-filter-links makes planner-create-task-from-info better at overriding dates Revision: planner--dev--1.0--patch-356 * planner-multi.el (planner-create-task-from-info): Handle overriding dates better. (planner-multi-filter-links): New convenience function for keeping or removing links. modified files: ChangeLog planner-multi.el 2005-03-29 20:29:29 GMT Jim Ottaway patch-53 Summary: merge latest, planner-appt advice fixes Revision: planner--jeho--1.0--patch-53 * planner-appt.el: added disable flag to all advice (planner-appt-use): enabling and updating disabled advice modified files: ChangeLog planner-appt.el 2005-03-29 17:54:55 GMT Sacha Chua patch-355 Summary: New options: planner-default-section, planner-sections Revision: planner--dev--1.0--patch-355 * planner.el (planner-default-section): New option. (planner-sections): New option. (planner-day-page-template): Mention planner-sections. (planner-plan-page-template): Mention planner-sections. (planner-seek-to-first): Look up symbols in planner-sections. (planner-narrow-to-note): Look up symbols in planner-sections. (planner-seek-task-creation-point): Look up section name. (planner-create-note): Look up section name for notes. Thanks to Tyler Weir for pointing out the need to make this more flexible. * planner.el (with-planner): Add edebug properties. Thanks to Jim Ottaway for the two-line tip. modified files: ChangeLog planner.el 2005-03-29 00:34:18 GMT Sacha Chua patch-354 Summary: Docfix: Publishing Calendars sample code. Bugfix: Remove cl dependency caused by declare Revision: planner--dev--1.0--patch-354 * planner-el.texi (Publishing Calendars): Docfix: Missing -hook. Thanks to Dryice Liu for pointing this out. * planner.el (with-planner): Remove that annoying declare thing. Will CVSisms never cease? modified files: ChangeLog planner-el.texi planner.el 2005-03-26 02:15:30 GMT Sacha Chua patch-353 Summary: planner-tasks-never-suppress-fixing-flag Revision: planner--dev--1.0--patch-353 * planner.el (planner-tasks-never-suppress-fixing-flag): New. (planner-save-buffers): Follow planner-tasks-never-suppress-fixing-flag. Thanks to Jeremy Cowgar for pointing out this need. modified files: ChangeLog planner.el 2005-03-23 01:56:55 GMT Sacha Chua patch-351 Summary: Docfix: Spamguard addresses and add other contributors Revision: planner--dev--1.0--patch-351 * planner-el.texi (Acknowledgements): Spamguard addresses. Add contributors. modified files: ChangeLog planner-el.texi 2005-03-22 10:28:48 GMT Sacha Chua patch-350 Summary: planner-expand-name: Tweak +tue Revision: planner--dev--1.0--patch-350 * planner.el (planner-expand-name): Tweak date offset so that +tue really is next Tuesday. modified files: ChangeLog planner.el 2005-03-22 05:54:01 GMT Sacha Chua patch-349 Summary: planner-id-find-task: XEmacs bugfix for infinite tasks Revision: planner--dev--1.0--patch-349 * planner-id.el (planner-id-find-task): Rewrite to eliminate XEmacs infinite duplication bug. Thanks to sf for reporting the bug and pointing out difference between XEmacs and Emacs regular expressions. modified files: ChangeLog planner-id.el 2005-03-22 04:38:48 GMT Sacha Chua patch-348 Summary: planner-calendar-html-tag-marker Revision: planner--dev--1.0--patch-348 * planner-calendar.el (planner-calendar-html-tag-marker): New option. Thanks to JM Ibanez for the patch. (planner-calendar-move-calendar-to-top-of-page-maybe): Use planner-calendar-html-tag-marker to make this more flexible. modified files: ChangeLog planner-calendar.el 2005-03-20 16:35:30 GMT Sacha Chua patch-347 Summary: planner-multi: Modify planner-tasks-equal-p Revision: planner--dev--1.0--patch-347 * planner-multi.el (planner-multi-tasks-equal-p): New function checks if the link text is a multilink. This fixes the planner-id infinite saving bug. Thanks to sf for pointing this out. (planner-tasks-equal-p): Defalias to planner-multi-tasks-equal-p. modified files: ChangeLog planner-multi.el 2005-03-17 14:01:14 GMT Sacha Chua patch-345 Summary: Replace mapc with mapcar for Emacs20 compatibility. Revision: planner--dev--1.0--patch-345 * planner-rss.el (planner-rss-add-item): Replace mapc call with mapcar. (planner-rss-add-note): Replace mapc call with mapcar. Thanks to Helge Kosuch and Rino Mardo for pointing this out. * planner-notes-index.el (planner-notes-index): Replace mapc call with mapcar. modified files: ChangeLog planner-notes-index.el planner-rss.el 2005-03-16 17:41:41 GMT Jim Ottaway patch-52 Summary: planner-appt sort bug Revision: planner--jeho--1.0--patch-52 * planner-appt.el (planner-appt-schedule-sort): fixed a problem with the sorting modified files: planner-appt.el 2005-03-16 07:52:51 GMT Dryice Liu patch-32 Summary: fix timeclock-summary publishing problem Revision: planner--dev--1.0--patch-32 * planner-timeclock-summary.el: The emacs-wiki simple table markup rule don't support a blank cell in the table, especially at the end of a line. So we need a placeholder to fix the published HTML table. (planner-timeclock-summary-placeholder-char): New option to define the placeholder character. Set it to " " to get the original behavior. (planner-timeclock-summary-make-text-table-day): Utilize planner-timeclock-summary-placeholder-char in the report table. modified files: planner-timeclock-summary.el 2005-03-15 22:42:50 GMT Jim Ottaway patch-50 Summary: planner-appt Revision: planner--jeho--1.0--patch-50 * planner-appt.el (planner-appt-schedule-sort): bug fixed modified files: planner-appt.el 2005-03-14 17:02:03 GMT Keith Amidon patch-1 Summary: Cleanup planner-trunk and fix task sorting bug Revision: planner--dev-kea--1.0--patch-1 2005-03-14 Keith Amidon * planner-trunk.el: make text fit on 80-column display (planner-trunk-list-plan-regexp) renamed planner-trunk-list-regexp (planner-trunk-task-completed-p) renamed planner-trunk-completed-p (planner-trunk-insert-heading) renamed planner-trunk-ins-heading (planner-trunk-do-trunk-section) shortened some local variable names * planner-trunk.el: fix bug involving tasks w/o a plan page (planner-trunk-task-plan-str) returns "" if no plan page for task (planner-trunk-do-trunk-section) removed no plan page special case, changed dummy non-matching regexp entry to "(_-)", which doesn't match an empty string and hopefully no one ever wants to use. modified files: planner-trunk.el {arch}/=tagging-method 2005-03-13 18:55:54 GMT Jim Ottaway patch-46 Summary: planner-authz: small modification Revision: planner--jeho--1.0--patch-46 * planner-authz.el (planner-authz-appt-regexp): added the nag marker modified files: planner-authz.el 2005-03-13 18:24:33 GMT Jim Ottaway patch-44 Summary: planner-authz: merge improvements Revision: planner--jeho--1.0--patch-44 * planner-authz.el: merged improvements [including planner-appt support] posted by the author on emacs-wiki-discuss modified files: planner-authz.el 2005-03-13 17:16:30 GMT Jim Ottaway patch-43 Summary: planner-el.texi: planner-appt documentation Revision: planner--jeho--1.0--patch-43 * planner-el.texi: made planner-appt documentation better: @subsubheadings instead of @unnumberedsubsubsec, used verbatim for the schedule examples to preserve spacing. modified files: planner-el.texi 2005-03-12 15:14:41 GMT Jim Ottaway patch-42 Summary: planner-el.texi updated planner-appt node Revision: planner--jeho--1.0--patch-42 * planner-el.texi: updated documentation in line with recent changes modified files: planner-appt.el planner-el.texi 2005-03-12 14:02:56 GMT Jim Ottaway patch-41 Summary: planner-appt changes Revision: planner--jeho--1.0--patch-41 * planner-appt.el: made compatible with appt-make-list, removed appt-check defeating, updated documentation, modified options to cyclical entries (planner-appt-schedule-cyclic-behaviour): new variable to determine cyclic entry behaviour (appt-make-list): new advice to preserve data (planner-appt-defeat-appt-check): removed (planner-copy-or-move-task): removed unecessary fiddling with hooks [left commented out in case it doesn't work] (planner-appt-schedule-add-cyclic-maybe): planner-app-schedule-add-cyclic-if-today remodelled and renamed (planner-appt-use): removed the do things at midnight code modified files: planner-appt.el 2005-03-11 02:50:51 GMT Sacha Chua patch-344 Summary: New macro with-planner ensures planner context Revision: planner--dev--1.0--patch-344 * planner.el (with-planner): New macro ensures we are in a planner project. (planner-task-info-from-string): Use with-planner. Thanks to Toby Allsopp for pointing this out. (planner-search-notes): Use with-planner. (planner-file-alist): Use with-planner. (planner-extract-tasks): Use with-planner. (plan): Use with-planner. (with-planner-update-setup): Remove redundant save-excursion. modified files: ChangeLog planner.el 2005-03-11 02:33:54 GMT Sacha Chua patch-343 Summary: Bugfixes: planner.el: remove unfontlocking code, add missing paren in planner-generate-index Revision: planner--dev--1.0--patch-343 * planner-trunk.el: Remove cl dependency. * planner.el (planner-create-task-from-info): Remove buggy unfontlocking code. * planner.el (planner-sort-tasks): Remove buggy unfontlocking code. * planner.el (planner-renumber-notes): Remove buggy unfontlocking code. * planner.el (planner-generate-index): Embarrassing trivial bugfix: missing paren modified files: ChangeLog planner-trunk.el planner.el 2005-03-10 09:50:33 GMT Sacha Chua patch-342 Summary: planner-trunk.el docfixes: not just for day page Revision: planner--dev--1.0--patch-342 * planner-trunk.el: Docfix. planner-trunk not just for day page. (planner-trunk-delete-non-task-lines): Docfix: commented-out alternative was buggy. modified files: ChangeLog planner-trunk.el 2005-03-10 09:11:03 GMT Sacha Chua patch-341 Summary: Update @cindex for Task Ranks documentation Revision: planner--dev--1.0--patch-341 * planner-el.texi (Task Ranks): Docfix: @cindex. Thanks to dryice for pointing this out. modified files: ChangeLog planner-el.texi 2005-03-10 08:26:46 GMT Sacha Chua patch-340 Summary: planner-create-task-from-info: Always call planner-create-task-hook Revision: planner--dev--1.0--patch-340 * planner.el (planner-create-task-from-info): Call planner-create-task-hook even if there is no day page. Thanks to Christophe Garion for the bug report. modified files: ChangeLog planner.el 2005-03-10 07:09:46 GMT Sacha Chua patch-338 Summary: New: planner-publish-dates-first-p Revision: planner--dev--1.0--patch-338 * planner.el (planner-generate-index): Honor planner-publish-dates-first-p. (planner-publish-dates-first-p): New option. Thanks to Chris Parsons for the patch. modified files: ChangeLog planner.el 2005-03-08 16:25:25 GMT Sacha Chua patch-337 Summary: planner-mhe fix from Christopher Garion: mh-path, utility functions Revision: planner--dev--1.0--patch-337 modified files: ChangeLog planner-mhe.el 2005-03-08 04:32:30 GMT Sacha Chua patch-336 Summary: New: planner-diary-add-entry Revision: planner--dev--1.0--patch-336 * planner-diary.el (planner-diary-add-entry): New function. Thanks to Jody Klymak for adapting my planner-config code. * planner-el.texi (Diary): Document planner-diary-add-entry. modified files: ChangeLog planner-diary.el planner-el.texi 2005-03-08 04:16:45 GMT Sacha Chua patch-335 Summary: Merge planner-appt from planner--jeho--1.0--patch-38 Revision: planner--dev--1.0--patch-335 * planner-el.texi (Appointments): New node copied from info file. Minor tweaks. modified files: ChangeLog planner-el.texi 2005-03-04 15:26:37 GMT Jim Ottaway patch-39 Summary: planner-appt: removed functions from planner-goto-hook Revision: planner--jeho--1.0--patch-39 * planner-appt.el (planner-copy-or-move-task): made this tidier with a let clause: what was I thinking with the previous unwind-protect thing? (planner-appt-insinuate-if-today): removed adding to planner-goto-hook modified files: planner-appt.el 2005-03-04 10:23:34 GMT Jim Ottaway patch-38 Summary: merge latest patches and defeat appt-check Revision: planner--jeho--1.0--patch-38 * planner-appt.el (planner-appt-show-alerts): change behaviour when there are no alerts (planner-appt-defeat-appt-check): new function to stop appt-check reseting the appointment list each day (planner-appt-midnight-functions, planner-appt-midnight-setup): new function and hook to do something each midnight. Intended for sustaining defeating of appt-check, but could be useful for other things... (planner-appt-use): added appt-check defeating modified files: ChangeLog planner-appt.el 2005-03-04 08:45:04 GMT Dryice Liu patch-29 Summary: Run hooks instead of call outline-show-all Revision: planner--dev--1.0--patch-29 * planner-trunk.el (planner-trunk-tasks-before-hook): new hook to run before foing the trunk. (planner-trunk-tasks-after-hook): new hook to run after the trunk. (planner-trunk-tasks): Remove the outline-show-all call and plant the above two new hooks. This is a more general way. modified files: planner-trunk.el 2005-03-03 01:59:44 GMT Dryice Liu patch-28 Summary: merge from Keith Amidon: now works with outline minor mode better Revision: planner--dev--1.0--patch-28 * planner-trunk.el: add a "nice to do" section in comenary. (planner-trunk-task-completed-p): new function. Return t if task-info is done or canceled. (planner-trunk-sort-tasks): utilize planner-trunk-task-completed-p. (planner-trunk-insert-heading): ditto. (planner-trunk-do-trunk-section): ditto. (planner-trunk-do-trunk): ditto. (planner-trunk-tasks): call outline-show-all before doing the trunk. Else the hidden sections are skip and extra headers are added. modified files: planner-trunk.el 2005-03-02 23:05:54 GMT Sacha Chua patch-334 Summary: planner-multi major bugfix for planner-make-link Revision: planner--dev--1.0--patch-334 * planner-multi.el (planner-make-link): Bugfix for the bugfix. Mrph. Clearly, the third argument should make this behave in the single-link case. modified files: ChangeLog planner-multi.el 2005-03-02 16:06:30 GMT Dryice Liu patch-26 Summary: use the helper functions Revision: planner--dev--1.0--patch-26 * planner-trunk.el (planner-trunk-tasks): use the helper functions modified files: planner-trunk.el 2005-03-02 15:51:59 GMT Dryice Liu patch-25 Summary: optional force trunk completed tasks together with non-completed tasks and minor improvements Revision: planner--dev--1.0--patch-25 * planner-trunk.el (cl): require cl (planner-trunk-task-plan-str): if planner-multi is not loaded, return task link first if it's not nil. So on plan pages we can always(with and without planner-multi) trunk by date. (planner-trunk-sort-tasks): also move cancled tasks to the "done" trunk. (planner-trunk-insert-heading): also support cancled tasks (planner-trunk-do-trunk): ditto. (planner-trunk-tasks): optional arg force to force trunk completed tasks together with non-completed tasks. (planner-trunk-rule-list): update ":type" to catch up the new format for customize. modified files: planner-trunk.el 2005-03-02 14:38:19 GMT Dryice Liu patch-24 Summary: merge from Keith Amidon: support trunk on plan pages and add sub-section headers Revision: planner--dev--1.0--patch-24 * planner-trunk.el: Lots of changes, changing planner-trunk-rule-list format to support trunk on plan pages and add sub-section headers. Here's the docstring of planner-trunk-rule-list, describing the new features: "List of rules for trunking tasks Each rule is a sublist of the form: (PAGE-REGEXP COMPLETE-HEADING TRUNK-SECTIONS-LIST) PAGE-REGEXP is used to select the set of trunk sections that should be used. It is matched against the name of the current planner page. If no matching PAGE-REGEXP is found, no trunking is done. If there is more than one match, the first one in the list is used. If COMPLETE-HEADING is nil, completed and not completed tasks will be in the same trunk, sorted according to `PLANNER-SORT-TASKS-KEY-FUNCTION'. If it is a string, it is the name of a sub-heading of the tasks section under which to sort completed tasks separately, in which case it will be the last subsection of the tasks section of the page. Each element of TRUNK-SECTIONS-LIST describes a trunk of the page. Elements can either be a simple TASK-PLAN-REGEXP, or a sublist of the form: (TASK-PLAN-REGEXP TRUNK-HEADING) The TASK-PLAN-REGEXP is matched against the plan page (or pages if you are using planner-multi) for the task. If more than one TASK-PLAN-REGEXP matches, the first one in the list is used. All tasks that match the same TASK-PLAN-REGEXP will be grouped together. The order of the groups will match the order of TRUNK-SECTIONS-LIST. Tasks that do not match any entry in TRUNK-SECTIONS-LIST will be in a separate group at the end of the tasks section. If the sublist form of an entry is used, TRUNK-HEADING is a name for the outline heading to be inserted at the top of the trunk. If TRUNK-SECTIONS-LIST contains a mix of items in the regexp and sublist forms, when tasks are present that match a regexp form entry, but no tasks are present that match the most recent preceeding sublist form entry in the list, the heading from the sublist form entry will be inserted anyway. In use, it will become obvious why this is desirable." modified files: planner-trunk.el 2005-03-02 07:23:00 GMT Dryice Liu patch-23 Summary: document planner-rank in info and some related docfixs Revision: planner--dev--1.0--patch-23 * planner-rank.el: doc fix to cache up the code changes * planner-el.texi (Task Ranks): new node describing planner-rank.el modified files: planner-el.texi planner-rank.el 2005-03-01 15:50:08 GMT Jim Ottaway patch-37 Summary: planner-appt fixed regexp Revision: planner--jeho--1.0--patch-37 * planner-appt.el (planner-appt-schedule-task-estimate-regexp): added the "nag" marker to the regexp modified files: planner-appt.el 2005-03-01 12:58:59 GMT Jim Ottaway patch-36 Summary: planner-appt added Henrik's nagging feature Revision: planner--jeho--1.0--patch-36 * planner-appt.el: added very plausible documentation for the nagging feature (planner-appt-task-regexp): modified to allow for nags (planner-appt-task-nagging-regexp): new regexp to match nags (planner-appt-task-nagging-p): new test for nagging (planner-copy-or-move-task): modified plan in progress pass-through to take nagging into account modified files: planner-appt.el 2005-03-01 12:38:07 GMT Jim Ottaway patch-35 Summary: planner-appt.el hooking and minor changes Revision: planner--jeho--1.0--patch-35 * planner-appt.el (planner-appt-task-add, planner-appt-task-delete): made these interactive again (planner-appt-use): move non-insinuating hooking to here (planner-appt-font-setup): added a test for today here so that it only highlights when it should [part of the non-insinuation changes] modified files: planner-appt.el 2005-03-01 09:17:05 GMT Sacha Chua patch-333 Summary: Revision: planner--dev--1.0--patch-333 * planner.el (planner-make-link): New parameter SINGLE forces link to be treated as a single link. Thanks to Dryice Liu for the bugfix suggestion and patch. (planner-annotation-from-planner-note): Single link. (planner-annotation-from-file): Single link. (planner-annotation-from-info): Single link. * planner-bibtex.el (planner-bibtex-annotation-new): Single link. * planner-bookmark.el (planner-bookmark-make-url): Single link. * planner-gnus.el (planner-gnus-annotation-from-message): Single link. (planner-gnus-annotation-from-summary): Single link. * planner-mhe.el (planner-mhe-annotation): Single link. * planner-vm.el (planner-vm-annotation-from-mail): Single link. * planner-w3m.el (planner-w3m-annotation-from-w3m): Single link. * planner-wl.el (planner-wl-annotation-from-wl): Single link. modified files: ChangeLog planner-bibtex.el planner-bookmark.el planner-gnus.el planner-mhe.el planner-multi.el planner-w3m.el planner-wl.el planner.el 2005-03-01 06:28:20 GMT Dryice Liu patch-21 Summary: fix problem if planner-multi is loaded and there are space in bookmark name Revision: planner--dev--1.0--patch-21 * planner-bookmark.el (planner-bookmark-make-url): With planner-multi-separator set to " " (the default), if there are space in the bookmark name, the defadviced version of planner-make-link will seperate the bookmark name by space and make several links, which is not what we want. Changing the call from planner-make-link to emacs-wiki-make-link fix this. modified files: planner-bookmark.el 2005-02-28 17:34:09 GMT Jim Ottaway patch-34 Summary: planner-appt changes Revision: planner--jeho--1.0--patch-34 * planner-appt.el: documentation changes (planner-schedule-task-estimate): redefined this as advice to the original function [just in case someone does (load "planner-schedule") after loading planner-appt (planner-appt-task-insinuate): moved the hooking elsewhere (planner-appt-task-de-insinuate): moved the unhooking elsewhere (planner-appt-schedule-get-cyclic-tasks): made this really have a no-of-days option (planner-appt-schedule-add-cyclic-if-today): more restricted version of planner-appt-schedule-add-cyclic (planner-appt-schedule-cyclic-insinuate): removed hooking into planner-goto-hook [not necessary] (planner-appt-use): did a bit of the hooking here so that one doens't have to use planner-appt-insinuate if one really doesn't want to modified files: planner-appt.el 2005-02-28 09:40:11 GMT Dryice Liu patch-20 Summary: merge Keith Amidon's bug fix and improvements Revision: planner--dev--1.0--patch-20 * planner-trunk.el (planner-trunk-delete-all-blank-lines): don't insert new line at the end of buffer, they will be added in planner-trunk-do-trunk. (planner-trunk-sort-tasks): be more lispy. New argument rule-list. (planner-trunk-do-trunk): Fix infinite loop problem when there's no tasks in the "* Tasks" section. New argument rule-list. Much more concise code. (planner-trunk-tasks): call planner-trunk-sort-tasks and planner-trunk-do-trunk with arguments. modified files: planner-trunk.el 2005-02-27 18:16:00 GMT Jim Ottaway patch-33 Summary: planner-apt changes Revision: planner--jeho--1.0--patch-33 * planner-appt.el: Added a warning about the experimental nature of planner-appt. (planner-appt-sort-schedule-on-update-flag): made this nil by default (planner-appt-calendar-insinuate): removed the confusing flag from this. modified files: planner-appt.el 2005-02-27 12:13:42 GMT Jim Ottaway patch-32 Summary: planner-appt: hooking Revision: planner--jeho--1.0--patch-32 * planner-appt.el (planner-appt-insinuate): added adding planner-appt-insinuate-if-today to planner-goto-hook modified files: planner-appt.el 2005-02-27 12:02:12 GMT Jim Ottaway patch-31 Summary: de-insinuation Revision: planner--jeho--1.0--patch-31 * planner-appt.el: Added a command planner-appt-de-insinuate that removes planner-appt from all planner hooks, since any breakage can interfere badly with planner. modified files: planner-appt.el 2005-02-27 11:16:06 GMT Jim Ottaway patch-30 Summary: corrected mistypes and appended to a hook Revision: planner--jeho--1.0--patch-30 * planner-appt.el: small documentation changes (planner-appt-update): corrected typographic error (planner-appt-insinuate-if-today): append planner-appt-update-for-write to the write hook modified files: ChangeLog planner-appt.el 2005-02-27 04:41:02 GMT Sacha Chua patch-332 Summary: planner-diary-include-all-output-flag: New option Revision: planner--dev--1.0--patch-332 * planner-diary.el (planner-diary-get-diary-entries): Honor planner-diary-include-all-output. (planner-diary-include-all-output-flag): New user option suggested by Raymond Zeitler. modified files: ChangeLog planner-diary.el planner-el.texi 2005-02-27 04:07:25 GMT Sacha Chua patch-331 Summary: Remove buggy unfontlock code from with-planner-update-setup Revision: planner--dev--1.0--patch-331 * planner.el (with-planner-update-setup): Remove buggy unfontlock code. modified files: ChangeLog planner.el 2005-02-26 18:41:24 GMT Jim Ottaway patch-29 Summary: tidying up Revision: planner--jeho--1.0--patch-29 * planner-appt.el: small documentation changes; moved lots of things around for code readability; nicer customization (planner-appt-write-file-hook): new global variable for the preferred write-hook (planner-appt-seek-to-end-of-current-section): new function: does what it says (planner-appt-live-task-regexp): new regular expression matching tasks that are not cancelled and not finished (planner-appt-de-wiki): made this more lispy with catch and throw [but couldn't find simple `loop' outside of `cl'] (planner-appt-show-alerts): new command to show a list of scheduled alerts (planner-appt-schedule-add-cyclic): made the sorting contingent upon planner-appt-sort-schedule-on-update-flag (planner-appt-update, planner-appt-insinuate-if-today): added some bullet-proofing to make sure there is an initial update modified files: planner-appt.el 2005-02-26 00:07:55 GMT Jim Ottaway patch-28 Summary: shuffling and gentle refining Revision: planner--jeho--1.0--patch-28 * planner-appt.el: moved things around for better reading (planner-appt-todays-page-p): new function (planner-appt-time-regexp): generalized regexps a bit (planner-appt-task-insinuate): removed planner-appt-update (planner-appt-update-for-write): moved the test for planner-appt-update-appts-on-save-flag to this function (planner-appt-schedule-insinuate): removed planner-appt-update (planner-appt-insinuate-if-today): added to local-write-file-hooks directly here (planner-appt-mark-calendar): a little consistency edit modified files: planner-appt.el 2005-02-25 18:39:09 GMT Jim Ottaway patch-27 Summary: updates to update Revision: planner--jeho--1.0--patch-27 changed all updating hooks to planner-appt-update modified files: planner-appt.el 2005-02-25 17:59:09 GMT Jim Ottaway patch-26 Summary: massive changes Revision: planner--jeho--1.0--patch-26 * planner-appt.el: documentation changes Moved lots of functions around around. Made font-locking work for schedules. Fixed a problem with the task-based method where it wasn't cleaning up after itself. Smoothed out the user interface, and integrated the two methods better, renamed a few functions to make them consistent. Changed after-save hooks to local-write-file-hooks Changed the hooking so that it only happens for today's plan page [pointless to have these hooks elsewhere, despite my earlier sentiments to the contrary] sorry about the terse change log modified files: planner-appt.el 2005-02-25 17:56:08 GMT Jim Ottaway patch-25 Summary: lots of little changes Revision: planner--jeho--1.0--patch-25 * planner-appt.el: documentation changes (planner-appt-update-appts-on-save-flag): moved up the file (planner-appt-font-lock-appointments-flag): option for font-locking (planner-appt-clear-appts, planner-appt-remember-appt): new functions (planner-appt-task-regexp): modified to match with whitespace after the @ (planner-copy-or-move-task): changed changed function names (--planner-appt-tasks-added-appts): new variable to track task-based appointments (planner-appt-task-add): now keeps track of the appointments it adds (planner-appt-add-appts-from-tasks): renamed to be consistent with planner-appt-add-appts-from-schedule, changed regexp usage (planner-appt-add-appts-from-schedule): uses new clean up and tracking functions (planner-appt-update, planner-appt-write-func): new unified update function and hook (planner-appt-methods): fiddled with the methods (planner-appt-face): renaming of planner-appt-add-face modified files: planner-appt.el 2005-02-25 17:44:32 GMT Jim Ottaway patch-24 Summary: documentation modifications Revision: planner--jeho--1.0--patch-24 * planner-appt.el: minor changes to the documentation modified files: planner-appt.el 2005-02-24 20:12:05 GMT Jim Ottaway patch-23 Summary: added cyclic schedule support Revision: planner--jeho--1.0--patch-23 * planner-appt.el (planner-appt-schedule-basic-regexp, planner-appt-schedule-regexp, planner-appt-schedule-appt-regexp): broke the schedule regexp up to make it useable for other purposes. (planner-appt-schedule-sort): new function for sorting the schedule (planner-appt-schedule-get-cyclic-tasks): new function that reads schedule entries from the `planner-cyclic-diary-file' (planner-appt-schedule-add-cyclic): new function to add cyclic schedule entries to today's schedule (planner-appt-schedule-cyclic-insinuate): cyclic schedule insinuation function (planner-appt-mark-calendar): a few cosmetic changes modified files: planner-appt.el 2005-02-24 19:39:27 GMT Jim Ottaway patch-22 Summary: merge Henrik's font lock code, minor documentation changes Revision: planner--jeho--1.0--patch-22 * planner-appt.el: some documentation changes merged patch from Henrik Hansen: 2005-02-24 Henrik S. Hansen * planner-appt.el: Added font highlighting for tasks. New faces: - planner-appt-added-face - planner-appt-overdue-face New functions: - planner-appt-task-highlight-face - planner-appt-task-highlight - planner-appt-update-tasks - planner-appt-font-setup (planner-appt-task-insinuate): added a planner-mode hook for planner-appt-font-setup. modified files: planner-appt.el 2005-02-23 21:26:43 GMT Jim Ottaway patch-21 Summary: rudimentary schoolboy error in planner-copy-or-move-task advice Revision: planner--jeho--1.0--patch-21 * planner-appt.el (planner-copy-or-move-task): fixed silly error checking for an appointment in the task modified files: planner-appt.el 2005-02-23 19:54:28 GMT Jim Ottaway patch-20 Summary: lots of changes Revision: planner--jeho--1.0--patch-20 2005-02-23 Jim Ottaway * planner-appt.el: Added copyright and licence notice. Created friendlier configuration functions `planner-appt-use-tasks', `planner-appt-use-schedule', and `planner-appt-use-tasks-and-schedule'. Modified documentation as appropriate. (planner-appt-earlier-than-now-p): Renamed `planner-appt-time-old-p' to the more informative `planner-appt-earlier-than-now-p'. Added `planner-appt-later-than-now-p' to satisfy a mania for symmetry. (planner-appt-schedule-appt-regexp): Modified so that it captures the second time in a schedule entry: it could be useful for some other schedule handling code. (planner-appt-use): Made this idempotent, substituting `add-to-list' for `push'. (planner-appt-task-add, planner-appt-task-delete): Added check that there is a current task. Without this there was an uninformative error message. Added optional argument INFO: use that instead of the current task info [useful to save visiting today's plan page to add appointments [see advice to `planner-copy-or-move-task']]. (planner-appt-task-delete): Return a list of deleted appointments in the format used in `appt-time-msg-list' [can be useful in some cases]. (planner-appt-task-member): Renamed `planner-appt-task-added-p' to this to hint that it behaves like `member'. (plan): Added advise to this so that the advice to planner-copy-or-move-task can know whether `plan' is being called; protected against error. I hate function advice! (planner-copy-or-move-task): Modified advice a lot to make it delete and add appointments correctly, and also to handle errors within the advised function. This seems to be the only advice that requires such elaborate handling: in the others any problems are trapped by the test for a current task line added to `planner-appt-task-delete'. Added handling for when `plan' has been called: don't carry a task forward if it is an appointment. (planner-schedule-task-estimate): Moved the require into this function to save loading if tasks are not being used. modified files: planner-appt.el 2005-02-22 14:20:17 GMT Dryice Liu patch-18 Summary: new planner-trunk.el to group tasks in day page Revision: planner--dev--1.0--patch-18 This file provide `planner-trunk-tasks', which will group the tasks in day pages according to `planner-trunk-rule-list'. new files: .arch-ids/planner-trunk.el.id planner-trunk.el 2005-02-21 17:49:59 GMT Jim Ottaway patch-19 Summary: merged task-based appointment alerts Revision: planner--jeho--1.0--patch-19 Merged code from Henrik Hansen's planner-task-appt.el code. modified files: planner-appt.el 2005-02-20 21:10:39 GMT Jim Ottaway patch-18 Summary: improved regexp and documentation changes Revision: planner--jeho--1.0--patch-18 * planner-appt.el (planner-appt-schedule-regexp): improved regexp ...and a few other comment changes modified files: planner-appt.el 2005-02-19 13:17:35 GMT Jim Ottaway patch-17 Summary: smarter and faster calendar markup Revision: planner--jeho--1.0--patch-17 * planner-appt.el (planner-appt-mark-calendar): added TO option; made it only do as much work as necessary modified files: planner-appt.el 2005-02-19 11:27:10 GMT Jim Ottaway patch-16 Summary: even more generous schedule regexp Revision: planner--jeho--1.0--patch-16 * planner-appt.el (planner-appt-schedule-regexp): the regexp now matches most [all?] imaginable formats for an appointment [and doesn't get misled by email addresses] modified files: planner-appt.el 2005-02-18 22:58:05 GMT Jim Ottaway patch-15 Summary: problems with appt-make-list Revision: planner--jeho--1.0--patch-15 Added some comments and advice about appt-make-list after discovering it wipes out prior appointments. modified files: planner-appt.el 2005-02-18 21:48:04 GMT Jim Ottaway patch-14 Summary: regexp tuning Revision: planner--jeho--1.0--patch-14 * planner-appt.el (planner-appt-schedule-regexp): made this more generous than it was before, so it should match, e.g. 12:00 | | foobie bletch which didn't match before. modified files: planner-appt.el 2005-02-18 17:25:46 GMT Jim Ottaway patch-13 Summary: fix my previous so-called 'fix' Revision: planner--jeho--1.0--patch-13 * planner-appt.el (planner-appt-insinuate): fixed error in this function introduced into the last patch; make the hook append as well modified files: planner-appt.el 2005-02-18 16:44:44 GMT Jim Ottaway patch-12 Summary: planner-mode-hook misfunction Revision: planner--jeho--1.0--patch-12 * planner-appt.el (planner-appt-insinuate): fixed wrong function added to planner-mode-hook modified files: planner-appt.el 2005-02-18 16:22:00 GMT Jim Ottaway patch-11 Summary: respect for exogenous appointments Revision: planner--jeho--1.0--patch-11 * planner-appt.el (planner-appt-schedule-to-appt): now respects appointments added outside of planner modified files: planner-appt.el 2005-02-18 15:00:10 GMT Jim Ottaway patch-10 Summary: planner-appt.el changes Revision: planner--jeho--1.0--patch-10 * planner-appt.el: (planner-appt-filename-to-date): new function (planner-appt-entry-marker): new face (planner-appt-mark-calendar): add marks in calendar when there is a day page (planner-appt-mark-calendar-maybe): mark the calendar conditionally (planner-appt-insinuate): added hook for conditional calendar marking modified files: planner-appt.el 2005-02-18 11:32:11 GMT Jim Ottaway patch-9 Summary: planner-appt.el Revision: planner--jeho--1.0--patch-9 * planner-appt.el: a new file that integrates schedules and appointments new files: .arch-ids/planner-appt.el.id planner-appt.el 2005-02-17 16:02:06 GMT Sacha Chua patch-330 Summary: planner-multi.el: planner-create-task-from-info should call the create-task hook Revision: planner--dev--1.0--patch-330 * planner-multi.el (planner-multi-separator): Docfix: Add note about emacs-wiki-link-at-point. (planner-create-task-from-info): Modify Jim Ottaway's patch-7, moving the planner-create-task-hook call outside the list. modified files: ChangeLog planner-multi.el 2005-02-16 16:57:42 GMT Jim Ottaway patch-7 Summary: added running planner-create-task-hook Revision: planner--jeho--1.0--patch-7 * planner-multi.el (planner-create-task-from-info): run planner-create-task-hook modified files: planner-multi.el 2005-02-16 14:56:25 GMT Sacha Chua patch-329 Summary: planner-multi-read-name: Check if str is null Revision: planner--dev--1.0--patch-329 * planner-multi.el (planner-multi-read-name): Check if str is null to distinguish default case properly. (string= nil "nil"), apparently. Thanks to Jim Ottaway for the patch. modified files: ChangeLog planner-multi.el 2005-02-16 13:05:51 GMT Jim Ottaway patch-5 Summary: fix handling of default in planner-multi-read-name Revision: planner--jeho--1.0--patch-5 * planner-multi.el (planner-multi-read-name): Surprisingly, perhaps, (string= nil "nil") returns t. So when completing-read-multiple returns nil (i.e., default), the test for when the actual string "nil" has been entered at the prompt is also passed for nil as well. This modification tests for the nil case before the "nil" case, fixing the problem. modified files: planner-multi.el 2005-02-16 04:58:58 GMT Sacha Chua patch-328 Summary: Merge jeho's changes fixing planner-id and planner-multi interaction; tweak implementation Revision: planner--dev--1.0--patch-328 * planner.el (with-planner-update-setup): Remove redundant save-excursion. * planner.el (planner-task-info-from-string): Do not use planner-task-line-regexp. Make status more flexible. * planner.el (planner-jump-to-linked-task-function): Convert into a hook. * planner.el (planner-jump-to-linked-task-basic): New. * planner.el (planner-find-task-function): Convert into a hook. * planner.el (planner-find-task-basic): New. * planner.el (with-planner-update-setup): Expand macro so that we don't need to require edebug. * planner-id.el (planner-id-find-task): NOTE: Change first parameter to task-info to be consistent with planner-find-task. Search for description if no task ID is specified. * planner-id.el (planner-id-jump-to-linked-task): Use planner-id-find-task. * planner-id.el (planner-jump-to-linked-task-function): Set instead of using advice. * planner-id.el (planner-find-task-function): Set instead of using advice. * planner-multi.el (planner-edit-task-description): Implement multi version. modified files: ChangeLog planner-id.el planner-multi.el planner.el 2005-02-16 01:47:37 GMT Sacha Chua patch-327 Summary: Relicense planner-el.texi to GPL from GFDL Revision: planner--dev--1.0--patch-327 * planner-el.texi: Change to GPL. * planner.el (planner-sort-tasks-by-link): Remove unnecessary skip-chars-forward. Thanks to John Sullivan for pointing this out. modified files: ChangeLog planner-el.texi planner.el 2005-02-15 15:06:32 GMT Jim Ottaway patch-3 Summary: fix interaction between task ids and multiple links Revision: planner--jeho--1.0--patch-3 * planner-id.el (planner-id-find-task, planner-find-task): Added this function and advice so that tasks are found correctly by id. * planner-multi.el (planner-update-task): Use the new update setup macro wrapper with-planner-update-setup in planner.el. * planner.el (planner-task-line-regexp, planner-task-info-from-string): New global variable to match a task line. * planner.el (with-planner-update-setup, planner-update-task): a macro wrapper for the update setup so that the code may be conveniently reused in planner-multi.el modified files: planner-id.el planner-multi.el planner.el 2005-02-15 14:53:23 GMT Jim Ottaway patch-2 Summary: planner-id.el regexp bug Revision: planner--jeho--1.0--patch-2 * planner-id.el (planner-id-regexp): missing + in regexp modified files: planner-id.el 2005-02-10 07:51:47 GMT Sacha Chua patch-326 Summary: planner-el.texi: Docfix: planner-update-wiki-project is not interactive Revision: planner--dev--1.0--patch-326 * planner-el.texi (Basic Configuration): Update note about planner-update-wiki-project which is not an interactive function. Thanks to Jeremy Cowgar for spotting this. modified files: ChangeLog planner-el.texi 2005-02-10 06:17:37 GMT Sacha Chua patch-325 Summary: planner-wl: Work with Wanderlust 2.12.0 Revision: planner--dev--1.0--patch-325 * planner-wl.el (planner-wl-annotation-from-wl): Merge Jeremy Cowgar's minor patch updating it to Wanderlust 2.12.0 modified files: ChangeLog planner-wl.el 2005-02-10 05:40:12 GMT Sacha Chua patch-324 Summary: planner-sort-tasks: Fix case where last line has task Revision: planner--dev--1.0--patch-324 * planner.el (planner-sort-tasks): Bugfix for end of buffer. Do not attempt to advance cursor past end of buffer as this results in obscure cannot-save bug. modified files: ChangeLog planner.el 2005-02-10 02:16:58 GMT Sacha Chua patch-323 Summary: planner-sort-tasks: Bugfix for infloop Revision: planner--dev--1.0--patch-323 * planner.el (planner-sort-tasks): Make sure we advance at least one character so that we don't infinite-loop. Thanks to Jeremy Cowgar for the bug report. modified files: ChangeLog planner.el 2005-02-08 15:52:09 GMT Sacha Chua patch-322 Summary: planner-bibtex: Make separator more flexible Revision: planner--dev--1.0--patch-322 * planner-bibtex.el (planner-bibtex-separator): New. (planner-bibtex-regexp): New. (planner-bibtex-annotation-new): Use planner-bibtex-separator. (planner-bibtex-annotation-old): Use planner-bibtex-separator. (planner-bibtex-browse-url): Use planner-bibtex-regexp modified files: ChangeLog planner-bibtex.el 2005-02-08 15:50:49 GMT Sacha Chua patch-321 Summary: planner-multi: Be graceful about missing crm Revision: planner--dev--1.0--patch-321 * planner-multi.el: Condition-case (require 'crm) instead of using CVS-style require. (planner-read-name): Check for completing-read-multiple. modified files: ChangeLog planner-multi.el 2005-02-08 15:24:47 GMT Sacha Chua patch-320 Summary: Fix: planner-menu should use planner-el info file Revision: planner--dev--1.0--patch-320 * planner.el (planner-menu): Use new Planner info file name planner-el. Thanks to Raymond Zeitler for the bug report. modified files: ChangeLog planner.el 2005-02-08 09:19:05 GMT Sacha Chua patch-319 Summary: planner-rank: Fix missing paren. Thanks to Chris parsons Revision: planner--dev--1.0--patch-319 modified files: ChangeLog planner-rank.el 2005-02-04 02:07:19 GMT Sacha Chua patch-318 Summary: planner-notes-tag: Remove page reference Revision: planner--dev--1.0--patch-318 * planner.el (planner-notes-tag): Strip the linked page reference when making lists of notes. This makes the lists easier to browse. modified files: ChangeLog planner.el 2005-02-03 14:03:14 GMT Sacha Chua patch-317 Summary: planner-rank.el fix: Emacs CVS-ism (read-number) Revision: planner--dev--1.0--patch-317 * planner-rank.el (planner-rank-read-importance-and-urgency): Bugfix: Remove Emacs CVS-ism (read-number). Thanks to ChrisMDP for pointing this out. modified files: ChangeLog planner-rank.el 2005-02-02 12:23:37 GMT Sacha Chua patch-315 Summary: planner-id fix: work with unnumbered tasks Revision: planner--dev--1.0--patch-315 * planner-id.el: Work with unnumbered tasks. Thanks to Jim Ottaway for the bug report. modified files: ChangeLog planner-id.el 2005-02-01 06:19:12 GMT Dryice Liu patch-16 Summary: Fix bug coorperating with planner-deadline Revision: planner--dev--1.0--patch-16 * planner-rank.el: when calling planner-rank-change from planner-deadline-change-hook, Emacs will complain "wrong type argument: number-or-marker-p" (planner-rank-calculate-urgency-from-deadline): use "value" to return what we want instead always return nil. (planner-rank-read-importance-and-urgency): call planner-deadline-days-left with task-info instead the wrong rank-info. modified files: planner-rank.el 2005-02-01 04:27:59 GMT Sacha Chua patch-314 Summary: planner-use-calendar-flag: Make calendar optional Revision: planner--dev--1.0--patch-314 * planner.el (planner-use-calendar-flag): New. (planner-read-date): Make calendar optional. modified files: ChangeLog planner.el 2005-02-01 04:22:56 GMT Sacha Chua patch-313 Summary: Bugfix: planner-expand-name Revision: planner--dev--1.0--patch-313 * planner.el (planner-expand-name): Bugfix; flipped "or" ignored offsets. modified files: ChangeLog planner.el 2005-02-01 04:19:03 GMT Sacha Chua patch-312 Summary: planner-expand-name: Specify dates by day name; ex: +5tue Revision: planner--dev--1.0--patch-312 * planner.el (planner-expand-name): Add +5tue2005.01.01 to planner-expand-name. You can now specify dates by day names. Example: -2mon = 2 Mondays ago. +fri = next Friday. (planner-expand-name-days-alist): New. modified files: ChangeLog planner.el 2005-02-01 03:35:52 GMT Sacha Chua patch-311 Summary: Fix: Add planner-menu to XEmacs menu Revision: planner--dev--1.0--patch-311 * planner.el (planner-menu): Add to XEmacs menu. Thanks to sf for reporting the bug and providing information. modified files: ChangeLog planner.el 2005-02-01 03:16:28 GMT Sacha Chua patch-310 Summary: planner.el: Don't font-lock minor operations Revision: planner--dev--1.0--patch-310 * planner.el (planner-create-task-from-info): Do not font-lock when creating tasks. (planner-sort-tasks): Minimize font-locking. (planner-renumber-notes): Minimize font-locking. (planner-update-task): Minimize font-locking. modified files: ChangeLog planner.el 2005-02-01 03:01:36 GMT Dryice Liu patch-13 Summary: autoload to calm down compiler Revision: planner--dev--1.0--patch-13 * planner-bookmark.el (planner-bookmark-make-url): autoload to calm down compiler. modified files: planner-bookmark.el planner-rank.el 2005-02-01 02:57:38 GMT Sacha Chua patch-309 Summary: planner-multi.el: Improve XEmacs support by making crm.el optional Revision: planner--dev--1.0--patch-309 * planner-multi.el (planner-multi-read-name): Make completing-read-multiple optional so that XEmacs users can try out planner-multi. However, this means they lose completion. For best results, get the crm.el library. modified files: ChangeLog planner-multi.el 2005-02-01 02:43:05 GMT Sacha Chua patch-308 Summary: planner-rank-change: Revert to Dryice's version Revision: planner--dev--1.0--patch-308 * planner-rank.el (planner-rank-change): Revert my change. Thanks to Dryice for pointing out bug introduced by rewrite. modified files: ChangeLog planner-rank.el 2005-01-31 02:31:15 GMT Sacha Chua patch-307 Summary: Merge planner-rank.el, modify, rename functions Revision: planner--dev--1.0--patch-307 * planner-rank.el: Rename importancy to importance, task categories to priorities. Rename -weighing- functions to -weighted-. Rewrite some of the implementations. (planner-rank-calculate-urgency-from-deadline): More flexible implementation. (planner-rank-test-algorithm): Rewrite to not use loop defvar. new files: .arch-ids/planner-rank.el.id planner-rank.el modified files: ChangeLog 2005-01-31 01:26:32 GMT Sacha Chua patch-306 Summary: MAJOR NOTE: 'Category' renamed to 'Priority', old 'Priority' renamed to 'Number' Revision: planner--dev--1.0--patch-306 * planner.el: NOTE: Rename categories to priorities (A, B, C) and the old priorities (1, 2, 3...) to numbers. This breaks old code and keybindings, but should be done for clarity. * planner-tasks-overview.el: Update references to categories and priorities. * planner-multi.el: Update references to categories and priorities. * planner-rdf.el: Update references to categories and priorities. * planner-rdf.owl: Update references to categories and priorities. * planner-el.texi: Update references to categories and priorities. * planner-multi.el (planner-multi-split): New. Use in other functions. modified files: ChangeLog planner-el.texi planner-multi.el planner-rdf.el planner-rdf.owl planner-tasks-overview.el planner.el 2005-01-31 01:06:54 GMT Sacha Chua patch-305 Summary: planner-deadline: helper functions, planner-deadline-change-hook Revision: planner--dev--1.0--patch-305 * planner-deadline.el: Merge patch from Dryice Liu. (planner-deadline-change-hook): New option. (planner-deadline-get-deadline-from-string): New helper function. (planner-deadline-get-current-deadline): New helper function. (planner-deadline-days-left): New helper function. (planner-deadline-update): Use planner-deadline-days-left. (planner-deadline-change): Run planner-deadline-change-hook. modified files: ChangeLog planner-deadline.el 2005-01-30 13:56:26 GMT Dryice Liu patch-11 Summary: add direction to the test table Revision: planner--dev--1.0--patch-11 * planner-rank.el (planner-rank-test-algorithm): add direction to the test table. modified files: planner-rank.el 2005-01-30 13:46:21 GMT Dryice Liu patch-10 Summary: new rank calculating functions taking weight in to consideration Revision: planner--dev--1.0--patch-10 * planner-rank.el: Now we have some algorithms that emphasis Importancy more than Urgency. (planner-rank-importancy-vs-urgency-factor): new customizable variable (planner-rank-rank-calculate-function): change the default to planner-rank-calculate-rank-weighing-rmsd. With the default settings, this one get a pretty reasonable result. I like this one :) (planner-rank-calculate-rank-weighing-average): new rank calculation function that take weight in to account. (planner-rank-calculate-rank-weighing-rmsd): Ditto. modified files: planner-rank.el 2005-01-30 12:27:14 GMT Dryice Liu patch-9 Summary: doc fix Revision: planner--dev--1.0--patch-9 * planner-rank.el: obey the good doc string style. Change the docstring of planner-rank-calculate-rank-* from a result table to asking the user to eval a sexp. This is "real time" if the user customized some parameters, and save lots of space :) modified files: planner-rank.el 2005-01-30 11:36:37 GMT Dryice Liu patch-8 Summary: don't update rank if we are not on a task line Revision: planner--dev--1.0--patch-8 * planner-rank.el: In plan pages, if there's planner-rank-regexp match outside the "* Tasks" section, when calling planner-rank-update-all, Emacs will complain "Wrong type argument: stringp, nil" on the matching line. This happens when there is a "* Timeclock" section in the plan page. (planner-rank-update-current-task): Check if we are on a task line before doing the update. (planner-rank-change): Ditto. Also protect the planner-rank-change-hook and re-indent. modified files: planner-rank.el 2005-01-30 10:51:51 GMT Dryice Liu patch-7 Summary: improve test function Revision: planner--dev--1.0--patch-7 * planner-rank.el (planner-rank-test-algorithm): now shows the result table in a new buffer, and take an argument to say which function to test. modified files: planner-rank.el 2005-01-30 06:03:35 GMT Dryice Liu patch-6 Summary: E= -> U= Revision: planner--dev--1.0--patch-6 * planner-rank.el: change from "E=" to "U=" in the task description to come on with the phrase change from Emergency to Urgency. modified files: planner-rank.el 2005-01-30 04:47:31 GMT Dryice Liu patch-5 Summary: New: planner-rank.el Revision: planner--dev--1.0--patch-5 * planner-rank.el: New feature to set task rank by Importancy and Urgency. new files: .arch-ids/planner-rank.el.id planner-rank.el 2005-01-30 04:06:15 GMT Dryice Liu patch-4 Summary: New hook planner-deadline-change-hook Revision: planner--dev--1.0--patch-4 * planner-deadline.el (planner-deadline-change-hook): New hook to run in function planner-deadline-change. (planner-deadline-change): run planner-deadline-change-hook at the end of this function. Note the planner-deadline-update call above: It's not necessory to update the whole page, Maybe we can change it to update the deadline of the current task only some time later. modified files: planner-deadline.el 2005-01-30 03:52:01 GMT Dryice Liu patch-3 Summary: New helper functions for getting deadline date Revision: planner--dev--1.0--patch-3 * planner-deadline.el (planner-deadline-get-deadline-from-string): return the deadline data in string. (planner-deadline-get-current-deadline): return the deadline date in the current task. modified files: planner-deadline.el 2005-01-30 03:46:29 GMT Dryice Liu patch-2 Summary: Move the calculation of how many days left out to be a function Revision: planner--dev--1.0--patch-2 * planner-deadline.el (planner-deadline-days-left): New function, return how many days are left for the given task. (planner-deadline-update): Call planner-deadline-days-left instead of doing the calculation itself. modified files: planner-deadline.el 2005-01-30 03:27:19 GMT Dryice Liu patch-1 Summary: New function planner-set-task-category Revision: planner--dev--1.0--patch-1 * planner.el (planner-set-task-category): New function, set the category of the current task. This is a helper function and not user visuable. modified files: planner.el 2005-01-28 05:28:57 GMT Sacha Chua patch-304 Summary: planner-ledger: now usable with new versions of ledger Revision: planner--dev--1.0--patch-304 * planner-ledger.el: Merge patch from Travis B. Hartwell making planner-ledger usable with new versions of ledger. planner-ledger is now more flexible. (planner-ledger-balance-accounts): Reasonable defaults. (planner-ledger-balance-args): New option. (planner-ledger-insert-maybe): Remove hardcoded things. modified files: ChangeLog planner-ledger.el 2005-01-26 14:37:12 GMT Sacha Chua patch-303 Summary: planner-mhe: Use message IDs Revision: planner--dev--1.0--patch-303 * planner-mhe.el (planner-mhe-get-message-id): New. Thanks to pll for suggesting it and patiently testing various buggy implementations. (planner-mhe-annotation): Use message ID. Merge planner-mhe-annotation-from-message and planner-mhe-annotation-from-folder. (planner-mhe-browse-url): Use message ID. modified files: ChangeLog planner-mhe.el 2005-01-24 10:27:26 GMT Sacha Chua patch-302 Summary: planner-deadline-change: Add deadlines to tasks without deadlines Revision: planner--dev--1.0--patch-302 * planner-deadline.el (planner-deadline-change): Allow the addition of deadlines to tasks without deadlines. Thanks to Dryice Liu for the suggestion. modified files: ChangeLog planner-deadline.el 2005-01-24 10:13:53 GMT Sacha Chua patch-301 Summary: New: planner-create-task-from-buffer-hook, minor bugfix to planner-timeclock-summary Revision: planner--dev--1.0--patch-301 * planner.el (planner-create-task-from-buffer-hook): New. Thanks to Dryice Liu for the suggestion. (planner-create-task-from-buffer): Append planner-create-task-from-buffer-hook. * planner-timeclock-summary.el (planner-timeclock-summary-update): Minor bugfix: Don't complain when there is no plan page. modified files: ChangeLog planner-timeclock-summary.el planner.el 2005-01-15 02:18:05 GMT Sacha Chua patch-300 Summary: Convert all defsubst to defun in my code Revision: planner--dev--1.0--patch-300 * planner.el: Convert all defsubst to defun. Defsubst cannot be advised or overridden, and lead to subtle bugs when you try it. Defuns provide more flexibility. * planner-calendar.el: Convert all defsubst to defun. * planner-multi.el: Convert all defsubst to defun. * planner-timeclock-summary.el: Convert all defsubst to defun. * planner-schedule.el: Convert all defsubst to defun. * planner-timeclock.el: Convert all defsubst to defun. * planner-logedit.el: Convert all defsubst to defun. * planner-diary.el: Convert all defsubst to defun. modified files: ChangeLog planner-calendar.el planner-diary.el planner-id.el planner-log-edit.el planner-multi.el planner-schedule.el planner-timeclock-summary.el planner-timeclock.el planner.el 2005-01-14 12:27:28 GMT Sacha Chua patch-299 Summary: planner-el.texi: Rename output file to planner-el.info, rewrite intro, reorganize Revision: planner--dev--1.0--patch-299 * planner-el.texi: NOTE: Rename to planner-el from PlannerMode for greater consistency with packaging. Rearrange intro section extensively. Group Planner features under tasks and notes. modified files: ChangeLog planner-el.texi renamed files: .arch-ids/planner.texi.id ==> .arch-ids/planner-el.texi.id planner.texi ==> planner-el.texi 2005-01-14 07:14:53 GMT Sacha Chua patch-298 Summary: planner-markup-note: Do not use emacs-wiki-bare-anchor-prefix Revision: planner--dev--1.0--patch-298 * planner.el (planner-markup-note): Do not use emacs-wiki-bare-anchor-prefix. modified files: ChangeLog planner.el 2005-01-14 02:27:19 GMT Sacha Chua patch-297 Summary: Handle nil dates better Revision: planner--dev--1.0--patch-297 * planner-multi.el (planner-copy-or-move-task): Allow nil dates. * planner.el (planner-copy-or-move-task): Allow nil dates. modified files: ChangeLog planner-multi.el planner.el 2005-01-14 00:37:42 GMT Sacha Chua patch-296 Summary: New: planner-expand-name-default allows undated tasks Revision: planner--dev--1.0--patch-296 * planner.el (planner-expand-name-default): New option allows people to make undated tasks easily. By default, keep the old behavior of scheduling tasks onto today. Set this to "nil" to create undated tasks. (planner-expand-name): Allow "." (today) and honor planner-expand-name-default. modified files: ChangeLog planner.el 2005-01-14 00:33:55 GMT Sacha Chua patch-295 Summary: planner-edit-task-description: Check old description for match Revision: planner--dev--1.0--patch-295 * planner-timeclock.el (planner-edit-task-description): Set current task only if old description matches. modified files: ChangeLog planner-timeclock.el 2005-01-13 00:22:30 GMT Sacha Chua patch-294 Summary: planner-bibtex-browse-url: Handle labels with : Revision: planner--dev--1.0--patch-294 * planner-bibtex.el (planner-bibtex-browse-url): Merge small patch from Jim Ottaway fixing case where bibtex labels contain :. modified files: ChangeLog planner-bibtex.el 2005-01-12 13:28:48 GMT Sacha Chua patch-293 Summary: planner-deadline: Allow deadline text anywhere Revision: planner--dev--1.0--patch-293 * planner-deadline.el (planner-deadline-update): Allow deadline text anywhere. * planner-id.el (planner-id-at-point): Trigger only for tasks. (planner-id-remove-tasks-on-page): Trigger only for tasks. (planner-id-keymap): Comment out. (planner-id-markup): Do not highlight with keymap. modified files: ChangeLog planner-deadline.el planner-id.el 2005-01-11 12:08:01 GMT Sacha Chua patch-292 Summary: New option: planner-use-plan-pages Revision: planner--dev--1.0--patch-292 * planner.el (planner-use-plan-pages): New option. Yes, you can turn plan pages off as well. Try not to have planner-use-day-pages and planner-use-plan-pages off at the same time. (planner-create-task-from-buffer): Follow planner-use-day-pages and planner-use-plan-pages. (planner-create-task): Follow planner-use-day-pages and planner-use-plan-pages. * planner.texi (Variables to Customize): Document planner-use-plan-pages. modified files: ChangeLog planner.el planner.texi 2005-01-11 11:21:03 GMT Sacha Chua patch-291 Summary: planner-timeclock-summary-day-range-entry: Watch out for nil strings Revision: planner--dev--1.0--patch-291 * planner-timeclock-summary.el (planner-timeclock-summary-day-range-entry): Make sure strings are not null before comparing them. modified files: ChangeLog planner-timeclock-summary.el 2005-01-11 11:20:00 GMT Sacha Chua patch-290 Summary: planner-multi-separator, planner-multi-read-name: Work with spaces! Yay! Revision: planner--dev--1.0--patch-290 * planner-multi.el (planner-multi-read-name): Allow the use of planner-multi-separator in completion. This means that spaces are now okay. (planner-multi-separator): Change the default to spaces again. modified files: ChangeLog planner-multi.el 2005-01-11 06:13:23 GMT Sacha Chua patch-289 Summary: planner-multi / planner-replan-note: Allow single-page notes Revision: planner--dev--1.0--patch-289 * planner-multi.el (planner-replan-note): Still allow single-page notes. modified files: ChangeLog planner-multi.el 2005-01-11 03:03:14 GMT Sacha Chua patch-288 Summary: planner-markup-task: Fix typo Revision: planner--dev--1.0--patch-288 * planner.el (planner-markup-task): Fix typo (missing parens). modified files: ChangeLog planner.el 2005-01-11 02:59:26 GMT Sacha Chua patch-287 Summary: planner-markup-task: Do not include second if missing priority Revision: planner--dev--1.0--patch-287 * planner.el (planner-markup-task): Do not include second if missing priority. modified files: ChangeLog planner.el 2005-01-11 00:23:22 GMT Sacha Chua patch-286 Summary: planner-markup-task: Do not include missing priority Revision: planner--dev--1.0--patch-286 * planner.el (planner-markup-task): Do not include priority if none is set. modified files: ChangeLog planner.el 2005-01-10 08:48:28 GMT Sacha Chua patch-285 Summary: New: planner-xtla.el Revision: planner--dev--1.0--patch-285 * planner-xtla.el: New from Stefan Reichör. * planner.texi (XTLA): Document planner-xtla.el new files: .arch-ids/planner-xtla.el.id planner-xtla.el modified files: ChangeLog planner.texi 2005-01-07 04:31:08 GMT Sacha Chua patch-284 Summary: planner-multi-note-xref bugfix: call planner-update-note Revision: planner--dev--1.0--patch-284 * planner-multi.el (planner-multi-note-xref): Call planner-update-note instead of planner-multi-update-note. Thanks to Dryice Liu for pointing this out. modified files: ChangeLog planner-multi.el 2005-01-06 09:16:03 GMT Sacha Chua patch-283 Summary: planner-multi bugfixes, related changes Revision: planner--dev--1.0--patch-283 * planner-rss.el (planner-rss-add-note): Use planner-format-note. (planner-rss-add-note): Better support for multiple pages. * planner-multi.el (planner-current-note-info): Docfix. Old doc referred to task. (planner-note-link): Docfix. Old doc referred to task. (planner-note-link-text): New. (planner-update-note): Promote planner-multi-note-update to advice of planner-update-note in planner.el. (planner-replan-note): Preliminary support for replanning notes. * planner.el (planner-find-file): Extract the page name from links. (planner-read-non-date-page): New argument INITIAL specifies the inital contents of the minibuffer. (planner-replan-note): Pass initial argument to make replanning easier. (planner-note-link-text): New. modified files: ChangeLog planner-multi.el planner-rss.el planner.el 2005-01-06 09:10:00 GMT Sacha Chua patch-282 Summary: planner-bookmark-add-note-title-flag: New user option Revision: planner--dev--1.0--patch-282 * planner-bookmark.el (planner-bookmark): Fix typo. (planner-bookmark-add-note-title-flag): New user option. (bookmark-set): Optionally add note title. modified files: ChangeLog planner-bookmark.el 2005-01-03 14:39:39 GMT Sacha Chua patch-281 Summary: planner.el (planner-replan-task): Fix typo Revision: planner--dev--1.0--patch-281 modified files: ChangeLog planner.el 2005-01-03 14:12:12 GMT Sacha Chua patch-280 Summary: planner-multi: planner-task-date: Bugfix for tasks without links Revision: planner--dev--1.0--patch-280 * planner-multi.el (planner-task-date): Recognize tasks without links. modified files: ChangeLog planner-multi.el 2005-01-03 14:07:58 GMT Sacha Chua patch-279 Summary: C-u M-x planner-replan-task picks up initial link text for easy editing Revision: planner--dev--1.0--patch-279 * planner.el (planner-read-name): Allow initial value. (planner-page-file): Force refresh of alist when it is mysteriously null. Fixes Debian bug #287078 reported by Brian Flaherty. (planner-replan-task): Prefix argument means default to current link text. * planner-multi.el: Require 'crm. (planner-multi-read-name): Allow initial value. (planner-read-name): Allow initial value. modified files: ChangeLog planner-multi.el planner.el 2005-01-03 10:41:44 GMT Sacha Chua patch-278 Summary: Minor tweaks to planner-id-add-task-id, planner-create-task Revision: planner--dev--1.0--patch-278 * planner-id.el (planner-id-add-task-id): Use convenience function. * planner.el (planner-create-task): Add space before annotation. modified files: ChangeLog planner-id.el planner.el 2005-01-03 10:39:46 GMT Sacha Chua patch-277 Summary: planner-multi: Numerous bugfixes, ugly hack for planner-read-name Revision: planner--dev--1.0--patch-277 * planner-multi.el (planner-multi-separator): Unbelievably ugly hack. Change default to ". (planner-task-info-from-string): Quote separator. (planner-update-task): Minor rearrangement. (planner-delete-task): Bugfix: Actually loop. (planner-make-link): Allow non-WikiCase links; force everything to link. (planner-create-task-from-info): Minor rearrangement. (planner-edit-task-description): New advice. (planner-multi-read-name): Ugly hack for completing multiple pages. (planner-read-name): Call planner-multi-read-name. (planner-multi-task-xref): Call planner-task-update. modified files: ChangeLog planner-multi.el 2005-01-03 07:00:01 GMT Sacha Chua patch-276 Summary: planner-multi: Read multiple pages Revision: planner--dev--1.0--patch-276 * planner-multi.el (planner-read-name): Read multiple pages. (planner-multi-separator): Default to "," to make multiple pages easier. modified files: ChangeLog planner-multi.el 2005-01-03 06:49:30 GMT Sacha Chua patch-275 Summary: planner-multi.el: Task support Revision: planner--dev--1.0--patch-275 * planner-multi.el (planner-multi-separator): Change default to " ". (planner-task-date): Determine the date from a list of links. (planner-multi-task-xref): New interactive function. (planner-copy-or-move-task): New advice. (planner-update-task): New advice. (planner-delete-task): New advice. (planner-make-link): New advice. (planner-create-task-from-info): New advice. (planner-multi-task-delete-this-page): New interactive function. (planner-current-note-info): planner-multi-separator is not a regexp. (planner-multi-note-update): Modify update code. (planner-multi-note-xref): Modify update code. (planner-multi-note-delete): Modify update code. (planner-multi-note-delete-this-page): Modify update code. modified files: ChangeLog planner-multi.el 2005-01-03 06:38:08 GMT Sacha Chua patch-274 Summary: planner-update-note: Fix excursion, restriction Revision: planner--dev--1.0--patch-274 * planner.el (planner-update-note): Clean up excursion and restriction saving. modified files: ChangeLog planner.el 2005-01-03 06:12:26 GMT Sacha Chua patch-273 Summary: Promote planner-update-note from experimental to planner.el Revision: planner--dev--1.0--patch-273 * planner.el (planner-update-note): Merge from planner-experimental.el. * planner-experimental.el: Move planner-update-note to main. modified files: ChangeLog planner-experimental.el planner.el 2005-01-02 12:01:02 GMT Sacha Chua patch-272 Summary: NOTE: planner-multi-xref-note: Rename from planner-multi-note-xref, other functions renamed Revision: planner--dev--1.0--patch-272 * planner-multi.el (planner-multi-note-xref): Rename from planner-multi-xref-note. modified files: ChangeLog planner-multi.el 2005-01-02 11:34:53 GMT Sacha Chua patch-271 Summary: Rename planner-multi-*-note functions to planner-multi-note-* Revision: planner--dev--1.0--patch-271 * planner-multi.el (planner-multi-note-update): Rename from planner-multi-update-note. (planner-multi-note-delete): Rename from planner-multi-delete-note. (planner-multi-note-delete-this-page): Rename from planner-multi-delete-note-this-page. Fix free variable. modified files: ChangeLog planner-multi.el 2005-01-02 00:34:56 GMT Sacha Chua patch-270 Summary: New: planner-replan-note Revision: planner--dev--1.0--patch-270 * planner.el (planner-delete-note): New interactive function. (planner-format-note): New. (planner-replan-note): New interactive function. (planner-note-date): New. (planner-note-plan): New. modified files: ChangeLog planner.el 2005-01-01 09:12:43 GMT Sacha Chua patch-269 Summary: Bugfix: planner-erc-annotation-from-erc Revision: planner--dev--1.0--patch-269 * planner-erc.el (planner-erc-annotation-from-erc): Fix IRC URL. modified files: ChangeLog planner-erc.el 2005-01-01 09:11:54 GMT Sacha Chua patch-268 Summary: planner-timeclock-summary: Don't choke when soemone logs in without comments Revision: planner--dev--1.0--patch-268 * planner-timeclock-summary.el (planner-timeclock-summary-extract-task-data): Don't choke on nil check-in. Thanks to Alan Schussman for the bug report. modified files: ChangeLog planner-timeclock-summary.el See ChangeLog.1 for earlier changes. ;; Local Variables: ;; coding: utf-8 ;; End: planner-el/ChangeLog.3000066400000000000000000002034771226462314700150520ustar00rootroot000000000000002006-08-06 02:32:41 GMT Michael Olson patch-71 Summary: Minor Makefile tweaks. Revision: planner-el--devel--0--patch-71 * Makefile: Abstract some mentions of Planner so that this can be more easily re-used by other projects. modified files: Makefile 2006-07-29 04:21:50 GMT Michael Olson patch-70 Summary: Manual: Fix syntax error introduced in last patch. Revision: planner-el--devel--0--patch-70 * planner-el.texi (Installing from Arch): Fix syntax error introduced in last patch. modified files: planner-el.texi 2006-07-29 04:16:59 GMT Michael Olson patch-69 Summary: Update maintainer info. Revision: planner-el--devel--0--patch-69 * AUTHORS: Mention that John Sullivan is the new maintainer. * planner-el.texi (Preface), Getting Help, Acknowledgements): Ditto. (Installing from Arch): Update the ArchZoom link for the new repository. modified files: AUTHORS planner-el.texi 2006-07-09 22:03:24 GMT Michael Olson patch-68 Summary: Manual: Heading fixes. Revision: planner-el--devel--0--patch-68 * planner-el.texi (Installing from a Source Archive) (Installing from Arch, Installing from Debian): Change a few @subsubsections to @subheadings. modified files: planner-el.texi 2006-07-09 21:04:18 GMT John Sullivan patch-67 Summary: Fix the gnus Summary mode keybinding. Revision: planner-el--devel--0--patch-67 modified files: planner-gnus.el 2006-07-08 19:25:03 GMT Michael Olson patch-66 Summary: Bring ChangeLog in sync. Revision: planner-el--devel--0--patch-66 * ChangeLog: Sync. modified files: ChangeLog 2006-07-06 09:31:30 GMT Jim Ottaway patch-65 Summary: planner-appt: fix match-string bug Revision: planner-el--devel--0--patch-65 * planner-appt.el (planner-appt-add-appts-from-schedule): wrap planner-appt-format-description in save-match-data. Fixes a bug where the match data was lost [only seems to happen for Emacs <= 21.3.1]. modified files: planner-appt.el 2006-06-30 06:47:42 GMT John Sullivan patch-64 Summary: Remove redundant parts about remember, and add missing index entries. Revision: planner-el--devel--0--patch-64 modified files: planner-el.texi 2006-06-30 03:31:22 GMT Michael Olson patch-63 Summary: Really fix double-escaping issue and protect task/note content. Revision: planner-el--devel--0--patch-63 * planner-publish.el (planner-publish-markup-task): Remove bad patch. Protect the task description from closing tags. (planner-publish-markup-note): Protect the note content from closing tags. (planner-publish-task-tag): Remove bad patch. Remove read-only properties from task description so that it gets interpreted by Muse. (planner-publish-note-tag): Remove read-only properties. modified files: planner-publish.el 2006-06-29 05:36:17 GMT Michael Olson patch-62 Summary: planner-authz: Update documentation. Revision: planner-el--devel--0--patch-62 * planner-authz.el: Update directions in header. (planner-authz-markup-tags): Use "diary-section" instead of "diary". (planner-authz-diary-section-tag): Rename from `planner-authz-diary-tag'. * planner-el.texi (Authz Access Restriction): Add Getting started and Diary markup sections. modified files: planner-authz.el planner-el.texi 2006-06-29 03:30:57 GMT Michael Olson patch-61 Summary: planner-publish: Fix double-escaping of task descriptions. Revision: planner-el--devel--0--patch-61 * planner-publish.el (planner-publish-task-tag): Fix double-escaping bug. modified files: planner-publish.el 2006-06-29 03:03:58 GMT Michael Olson patch-60 Summary: Quick grammar fix in README. Revision: planner-el--devel--0--patch-60 * README: Grammar fix. modified files: README 2006-06-28 21:03:18 GMT Michael Olson patch-59 Summary: Add load-path example for Remember. Revision: planner-el--devel--0--patch-59 * scripts/planner-build.el: Add a load-path example for Remember. modified files: scripts/planner-build.el 2006-06-28 20:49:58 GMT Michael Olson patch-58 Summary: Explain a prerequisite for compilation. Revision: planner-el--devel--0--patch-58 * scripts/planner-build.el: Use a more standard default path for each of the extensions. * planner-el.texi (Advanced Installation): Mention scripts/planner-build.el. * README: Ditto. modified files: README planner-el.texi scripts/planner-build.el 2006-06-28 01:48:09 GMT Michael Olson patch-57 Summary: Mention Emacs Muse in README. Revision: planner-el--devel--0--patch-57 * README: Mention that Emacs Muse must be installed before compiling. modified files: README 2006-06-27 04:26:04 GMT Michael Olson patch-56 Summary: Include autoloads file in the distribution. Revision: planner-el--devel--0--patch-56 * Makefile (distclean, dist): Include autoloads file in the distribution. modified files: Makefile 2006-06-27 03:56:26 GMT Michael Olson patch-54 Summary: Fix mailing list instructions in README. Revision: planner-el--devel--0--patch-54 * README: Fix URL for mailing list instructions. modified files: README 2006-06-27 03:45:34 GMT Michael Olson patch-53 Summary: Release Planner 3.41. Revision: planner-el--devel--0--patch-53 * Makefile.defs (VERSION): Set to 3.41. * NEWS: Update. * planner-el.texi: Set version to 3.41. (Why Use Planner, Tasks, Example Page): Use new mailing list address. * planner.el (planner-version): Release Planner 3.41. modified files: ChangeLog Makefile.defs NEWS planner-el.texi planner.el 2006-06-26 23:26:25 GMT Michael Olson patch-52 Summary: Document planner2diary.py. Revision: planner-el--devel--0--patch-52 * planner-el.texi (Diary): Document planner2diary.py. This completes the documentation part of the release plans. * planner2diary.py: Require /usr/bin/python instead of /usr/bin/python2.2. modified files: planner-el.texi planner2diary.py 2006-06-26 23:18:05 GMT Michael Olson patch-51 Summary: Document planner-report.el. Revision: planner-el--devel--0--patch-51 * planner-el.texi: Mention filenames in menus as much as possible. (Status Reports): Document planner-report.el. modified files: planner-el.texi 2006-06-23 13:54:58 GMT Michael Olson patch-50 Summary: Fix bug in last patch. Revision: planner-el--devel--0--patch-50 * planner.el (allout-mode-leaders): Make this use `add-hook' rather than `add-to-list' to avoid load errors. modified files: planner.el 2006-06-23 04:08:22 GMT Michael Olson patch-49 Summary: Make allout and Planner work better together by default. Revision: planner-el--devel--0--patch-49 * planner.el: Make allout mode recognize our special note syntax. Thanks to Bill White and Steven Lumos for the code snippet and research. modified files: planner.el 2006-06-22 03:29:38 GMT Michael Olson patch-48 Summary: Document planner-registry.el. Revision: planner-el--devel--0--patch-48 * planner-el.texi (planner-registry): Document the planner-registry.el file. * planner-registry.el: Clarify directions in header. modified files: planner-el.texi planner-registry.el 2006-06-20 18:10:46 GMT Michael Olson patch-47 Summary: Document through planner-publish.el. Revision: planner-el--devel--0--patch-47 * ChangeLog: Update. * planner-el.texi (Publishing Planner pages): New section that documents planner-publish.el. (PSVN): New section that documents planner-psvn.el. * planner-publish.el (planner-html-inner-header): (planner-html-inner-footer): Docfix. modified files: ChangeLog planner-el.texi planner-publish.el 2006-06-18 03:20:47 GMT John Sullivan patch-46 Summary: Document planner-zoom. Revision: planner--main--1.0--patch-59 modified files: planner-el.texi 2006-06-16 03:59:59 GMT Michael Olson patch-58 Summary: Spot check documentation through planner-gnus.el. Revision: planner--main--1.0--patch-58 * planner-el.texi (Planner-Diary Advanced Features): Add a few index entries. Document planner-export-diary.el. (Emacs Relay Chat): Update the syntax. modified files: planner-el.texi 2006-06-08 21:57:22 GMT Michael Olson patch-57 Summary: planner-el.texi: Use shared Arch archive in instructions. Revision: planner--main--1.0--patch-57 * planner-el.texi (Installing from Arch): Use shared archive instead of my personal archive. modified files: planner-el.texi 2006-06-08 21:36:15 GMT Michael Olson patch-56 Summary: Document new mailing lists in the manual. Revision: planner--main--1.0--patch-56 * planner-el.texi (Getting Help): Document new mailing lists. (Overview, Review, Sample Configuration Files): Point to Getting Help section for mailing list information. modified files: planner-el.texi 2006-06-08 20:54:08 GMT Michael Olson patch-55 Summary: Update NEWS. Revision: planner--main--1.0--patch-55 * NEWS: Update. modified files: NEWS 2006-06-08 20:26:57 GMT Michael Olson patch-54 Summary: Move Debian stuff to its own branch. Revision: planner--main--1.0--patch-54 removed files: debian/.arch-ids/=id debian/.arch-ids/NEWS.id debian/.arch-ids/README.Debian.id debian/.arch-ids/changelog.id debian/.arch-ids/compat.id debian/.arch-ids/control.id debian/.arch-ids/copyright.id debian/.arch-ids/emacsen-install.id debian/.arch-ids/emacsen-remove.id debian/.arch-ids/emacsen-startup.id debian/.arch-ids/planner-el.docs.id debian/.arch-ids/planner-el.info.id debian/.arch-ids/rules.id debian/NEWS debian/README.Debian debian/changelog debian/compat debian/control debian/copyright debian/emacsen-install debian/emacsen-remove debian/emacsen-startup debian/planner-el.docs debian/planner-el.info debian/rules removed directories: debian debian/.arch-ids 2006-06-05 15:52:57 GMT Michael Olson patch-53 Summary: Make Planner's keymap inherit from Muse's keymap. Revision: planner--main--1.0--patch-53 * planner.el (planner-mode-map): Apply patch from Adrian Aichner that inherits the keymap from Muse, rather than copying it. We fall back to copying it if the proper functionality does not exist in the user's version of Emacs. modified files: AUTHORS planner.el 2006-06-01 13:54:24 GMT Michael Olson patch-52 Summary: Add explanation for timeclock.el error. Revision: planner--main--1.0--patch-52 * contrib/timeclock.el: Add an explanation of why we error out if the person is not using XEmacs. * debian/emacsen-startup: Put Planner's contrib directory at the end of the load-path. modified files: ChangeLog ChangeLog.2005 Makefile.defs contrib/timeclock.el debian/changelog debian/emacsen-startup 2006-05-30 21:14:09 GMT Michael Olson patch-51 Summary: Avoid a backtrace when using planner-calendar and not publishing. Revision: planner--main--1.0--patch-51 * planner.el (planner-published-file): Avoid error when not publishing. (planner-yesterday): Docfix. (planner-tomorrow): New function that returns the date for tomorrow. modified files: planner.el 2006-05-29 14:22:16 GMT Michael Olson patch-50 Summary: Make ChangeLog conform to conventions better. Revision: planner--main--1.0--patch-50 * ChangeLog: Renamed from ChangeLog.2006 in order to follow Emacs conventions better. Specify the buffer encoding. Add helpful notices at the bottom of this and ChangeLog.2005. modified files: ChangeLog ChangeLog.2004 ChangeLog.2005 NEWS debian/rules renamed files: .arch-ids/ChangeLog.2006.id ==> .arch-ids/ChangeLog.id ChangeLog.2006 ==> ChangeLog 2006-05-26 14:44:08 GMT Michael Olson patch-49 Summary: Display a helpful message if muse-project-alist undefined. Revision: planner--main--1.0--patch-49 * planner.el (planner-display-warning): New function that displays a warning window. This is useful for longer explanations of errors. (plan): Display a helpful message if `muse-project-alist' is not defined. modified files: planner.el 2006-05-25 01:20:42 GMT Michael Olson patch-48 Summary: Fix lock up with old delegated task mark. Revision: planner--main--1.0--patch-48 * planner.el (planner-marks-regexp): Docfix. (planner-task-regexp): Don't include marks; be more lenient, since planner-id uses this as a metric for finding a task, and we don't want tasks with strange marks to cause it not to find a task. (plan): Indentation. modified files: planner.el 2006-05-23 22:14:14 GMT Michael Olson patch-46 Summary: Remove duplicate note links when publishing. Revision: planner--main--1.0--patch-46 * planner-publish.el (planner-publish-note-tag): Ensure that a page cannot appear in both link and categories. modified files: planner-publish.el 2006-05-23 16:19:01 GMT Michael Olson patch-45 Summary: Remove task IDs when publishing. Revision: planner--main--1.0--patch-45 * planner-id.el ("planner-publish"): Remove Task IDs and anything else that uses the ID syntax when publishing. modified files: planner-id.el 2006-05-18 20:05:12 GMT Michael Olson patch-44 Summary: Publish diary sections in a meaningful way. Revision: planner--main--1.0--patch-44 * planner-publish.el (planner-publish-markup-tags): Add entry for diary-section. (planner-xml-markup-strings, planner-html-markup-strings): Add strings for diary section. (planner-html-style-sheet): Add CSS elements for Diary section. (planner-publish-diary-section-tag): New function that publishes the diary in a way that preserves line breaks, using the verse tag function. (planner-section-tagnames): Transform Diary sections to diary-section tags. modified files: planner-publish.el 2006-05-18 16:40:36 GMT Michael Olson patch-43 Summary: Make notes publish with nicer default CSS elements. Revision: planner--main--1.0--patch-43 * planner-publish.el (planner-html-style-sheet): Add style elements for Notes section. This causes the note anchors to be placed on the same line as note headings, which is the way it used to be. modified files: planner-publish.el 2006-05-17 21:43:59 GMT Michael Olson patch-42 Summary: Work on calendar, manual, and index generation. Revision: planner--main--1.0--patch-42 * planner-calendar.el: Fix example in header. Remove the word "wiki" from everything, since "page" works better. (planner-calendar-coerce-day-page): New function that determines which day page to base the calendar on. (planner-calendar-from-page): Use `planner-calendar-coerce-day-page'. Check for null page name. (planner-calendar-create-today-link): Make sure that the page we are linking to actually exists. This function should now be safe to add globally to muse-after-publish-hook. (planner-publish-calendar-tag): If no calendar is returned, don't insert anything. ("planner-publish-finalize-regexps"): Use a better regexp to match the calendar tag, so that it is processed correctly. * planner-el.texi: Add subheadings for Keys, Options, and Functions, if applicable. (Publishing Calendars): Mention "page" and "arrows" options. Mention workaround for problem where the text in the arrows doesn't get published correctly. Give working example for planner-calendar-create-today-link. * planner.el (planner-published-file): Try to figure out where the file exists, if the output directory is not specified. This could be more elaborate to handle multiple source directories, but I haven't gotten around to that yet. (planner-index-as-string): Add exclude-daypages option for those who do not want day pages to show up in the index. modified files: planner-calendar.el planner-el.texi planner.el 2006-05-09 00:30:01 GMT Michael Olson patch-41 Summary: planner-el.texi: Update location of schedule.el. Revision: planner--main--1.0--patch-41 * planner-el.texi (Timeclock): Note that timeclock.el comes with GNU Emacs, and direct XEmacs users to use the version that comes with Planner in the contrib directory. (schedule.el): Use correct URL and note that this comes with Planner. Thanks to Adrian Aichner for the report. modified files: ChangeLog.2006 Makefile.defs debian/changelog planner-el.texi 2006-04-26 19:59:37 GMT Michael Olson patch-40 Summary: planner-calendar: Default to today if not publishing a day page. Revision: planner--main--1.0--patch-40 * planner-calendar.el (planner-calendar-from-wiki): Default to current day if we're not publishing a day page. modified files: planner-calendar.el 2006-04-26 19:55:13 GMT Michael Olson patch-39 Summary: Add default CSS elements for calendar stuff. Revision: planner--main--1.0--patch-39 * planner-publish.el (planner-html-style-sheet): Add some default CSS elements for calendar stuff. modified files: planner-publish.el 2006-04-26 19:35:10 GMT Michael Olson patch-38 Summary: planner-calendar: Surround generated calendar with
tag. Revision: planner--main--1.0--patch-38 * planner-calendar.el: Fix example. (planner-publish-calendar-tag): Surround in a
section for ease of use. * planner-el.texi (Publishing Calendars): Make the example simpler. * planner-publish.el (planner-insert-markup): If we're using Muse 3.02.6, manually make the region read-only. modified files: Makefile.defs debian/changelog planner-calendar.el planner-el.texi planner-publish.el 2006-04-26 18:09:14 GMT Michael Olson patch-37 Summary: Minor docfix. Revision: planner--main--1.0--patch-37 * planner-publish.el (planner-publish-prepare-buffer) (planner-publish-finalize-buffer): Docfix. modified files: planner-publish.el 2006-04-26 18:01:36 GMT Michael Olson patch-36 Summary: Make publishing of calendars work better using a new method. Revision: planner--main--1.0--patch-36 * planner-calendar.el: Docfix. Recognize tags even in the header and footer. (planner-calendar-insert-calendar-maybe) (planner-calendar-move-calendar-to-top-of-page-maybe): Remove, since they are not needed by the new method. * planner-el.texi (Publishing Calendars): Update. * planner-publish.el (planner-publish-prepare-regexps): New option that specifies the publishing regexps to apply before doing other publishing. (planner-publish-finalize-regexps): New option that specifies the publishing regexps to apply after doing other publishing. (planner-publish-prepare-buffer): Use planner-publish-prepare-regexps. (planner-publish-finalize-buffer): New function that finalizes Planner buffers after publishing. (planner-section-tagnames): Fix ordering error. modified files: planner-calendar.el planner-el.texi planner-publish.el 2006-04-26 03:22:20 GMT Michael Olson patch-35 Summary: Use h2, h3, ... for headings. Revision: planner--main--1.0--patch-35 * planner-publish.el (planner-publish-markup-tags) [title]: Accept attributes. (planner-html-markup-strings) [planner-begin-title, planner-end-title]: Use normal style headings, i.e. h2. (planner-html-style-sheet): Remove nested title hacks. (planner-publish-markup-note): Use title level of 3. (planner-publish-title-tag): Accept attributes. Call muse-markup-text with a level argument. (planner-publish-section): Store level as heading level + 1, since the topmost level heading should be h2. modified files: planner-publish.el 2006-04-25 22:03:34 GMT Michael Olson patch-34 Summary: Fix a paragraph publishing problem near end of file. Revision: planner--main--1.0--patch-34 * planner-publish.el (planner-html-markup-strings) [planner-end-note-categories]: Remove newline. (planner-publish-prepare-buffer): Rework to use the Muse markup engine. (planner-publish-markup-note): Docfix. (planner-publish-nested-section-tag): Docfix. (planner-publish-notes-section-tag): Insert newline. (planner-publish-note-tag): Insert newline. (planner-sectionalize-delimiter, planner-sectionalize-page) (sectionalize-markup-tagname, sectionalize-markup-tagname) (sectionalize): Remove. (planner-publish-section-close): New function that finds where the closing tag of DEPTH should go, and inserts TEXT. (planner-section-tagnames): Mapping of sections to their tag name. (planner-publish-section-tagname): New function that finds the tag name for the given section. (planner-publish-section): New function that publishing the current heading as a section. This should fix a problem with sections at the end of a file, given only one newline at end. modified files: planner-publish.el 2006-04-09 19:29:19 GMT Michael Olson patch-33 Summary: manual: Fix errors introduced in last patch. Revision: planner--main--1.0--patch-33 * planner-el.texi: Fix a couple of errors. modified files: planner-el.texi 2006-04-09 19:27:03 GMT Michael Olson patch-32 Summary: manual: Remove use of old Planner variables. Revision: planner--main--1.0--patch-32 * planner-el.texi: Remove use of old Planner variables. Thanks to Sebastian Luque for the report. (Creating Your Planner): Clarify comment. (Basic Configuration): Remove node, since its content is presented elsewhere. (Annotations, Publishing): Don't use old Planner variables in explanation. (iCal Task Publication): Give a more up-to-date example. modified files: planner-el.texi 2006-04-08 02:57:43 GMT Michael Olson patch-31 Summary: Prepare new Debian package for Arch snapshot. Revision: planner--main--1.0--patch-31 * ChangeLog.2006: Update. * debian/changelog: Prepare new Debian package for Arch snapshot. modified files: ChangeLog.2006 Makefile.defs debian/changelog 2006-04-08 01:34:44 GMT Michael Olson patch-30 Summary: planner-registry: Minor code cleanup. Revision: planner--main--1.0--patch-30 * planner-registry.el (planner-registry-show): Remove boundp check. modified files: planner-registry.el 2006-04-08 01:32:20 GMT Michael Olson patch-29 Summary: Include planner-registry.el. Revision: planner--main--1.0--patch-29 * planner-registry.el: New file that implements a registry of URLs and Planner annotations. This used to be called muse-registry.el, but it has been renamed to planner-registry.el since it fits better with Planner. new files: .arch-ids/planner-registry.el.id planner-registry.el modified files: AUTHORS 2006-04-02 18:20:31 GMT Michael Olson patch-28 Summary: Correct several regexps. Revision: planner--main--1.0--patch-28 If a regexp has a character set negation, make sure it includes the newline, so that newlines aren't matched. modified files: planner-appt.el planner-bibtex.el planner-deadline.el planner-erc.el planner-id.el planner-mhe.el planner-rdf.el planner-tasks-overview.el planner-timeclock.el planner-vm.el planner.el 2006-03-29 20:23:27 GMT Andrew J. Korty patch-25 Summary: Merge some authz fixes. Revision: planner--main--1.0--patch-27 * planner-authz.el (planner-authz-fix-list-item): new function to move the
  • tags to the inside to avoid a blank bullet when a list item is totally access controlled (planner-authz-markup-regexps): use it (planner-authz-index-as-string): use tags to mark up the index and rely on the new regexp entry to clean up the results (planner-authz-multi-union): declare `sublist' modified files: planner-authz.el 2006-03-27 23:52:31 GMT Michael Olson patch-25 Summary: planner-erc: Improve greatly. Revision: planner--main--1.0--patch-25 * planner-erc.el: Update the syntax for IRC URLs. Add warning for users of old versions of ERC. (planner-erc-url-regexp): New variable that specifies the syntax of IRC URLs. (planner-erc-annotation-from-erc): Use `erc-server-announced-name'. (planner-erc-browse-url): Figure out the desired chat buffer. If no chat buffer exists for the given URL, connect to the server. modified files: planner-erc.el 2006-03-25 04:46:53 GMT Michael Olson patch-24 Summary: planner-zoom.el: New file used for navigating Planner pages. Revision: planner--main--1.0--patch-24 * AUTHORS: Bookkeeping. * planner.el (planner-remove-if-not): New function that implements a simplified version of `remove-if-not'. * planner-zoom.el: New file by Gregory Novak that implements easy navigation of Planner pages. new files: .arch-ids/planner-zoom.el.id planner-zoom.el modified files: AUTHORS planner.el 2006-03-23 14:14:17 GMT Michael Olson patch-23 Summary: planner-psvn.el: Install update from author. Revision: planner--main--1.0--patch-23 * planner-psvn.el: Apply modified patch from Stefan Reichör that improves compatibility with newer versions of psvn.el and pops to the diff buffer. modified files: planner-psvn.el 2006-03-15 12:38:11 GMT Jim Ottaway patch-19 Summary: Merged from jeho@jeho.org--2005 (patch 56-57), mwolson@gnu.org--2006-planner-el (patch 16-19) Revision: planner--main--1.0--patch-21 * planner-appt.el (planner-appt-forthcoming-show-day-names-flag): New option that indicates whether to show day names in forthcoming appointments. (planner-appt-forthcoming-format): Add day name insertion. * planner-el.texi: Add documentation about new feature [and also for planner-appt-forthcoming-repeat-date-string]. modified files: planner-appt.el planner-el.texi 2006-03-14 21:13:28 GMT Michael Olson patch-20 Summary: planner-appt: Mention that documentation is available in Planner manual. Revision: planner--main--1.0--patch-20 * planner-appt.el: Mention that further details are available in the Planner manual. modified files: planner-appt.el 2006-03-14 20:03:31 GMT Michael Olson patch-19 Summary: planner-calendar: Fix publishing bug. Revision: planner--main--1.0--patch-19 * planner-calendar.el (planner-calendar-html-tag-marker): Use the correct value so that the calendar is published properly. Thanks to Christian Clercin and René. modified files: planner-calendar.el 2006-03-11 15:29:42 GMT Jim Ottaway patch-15 Summary: Merged from jeho@jeho.org--2005 (patch 54-55), mwolson@gnu.org--2006-planner-el (patch 14-15) Revision: planner--main--1.0--patch-18 * planner-appt.el (planner-fit-window-to-buffer): Use shrink-window-if-large-than-buffer if fit-window-to-buffer is not available. (planner-appt-forthcoming-regexp): Remove the shyness from the groups: this makes it match ok in XEmacs [don't know why it didn't before though]. modified files: planner-appt.el 2006-03-13 03:43:23 GMT Michael Olson patch-17 Summary: Add COPYING file; do bookkeeping. Revision: planner--main--1.0--patch-17 * COPYING: New file containing the GNU General Public License. * AUTHORS: Bookkeeping. * README: Add License section. * planner*.el: Update headers. new files: .arch-ids/COPYING.id COPYING modified files: AUTHORS README planner-accomplishments.el planner-appt.el planner-authz.el planner-bbdb.el planner-bibtex.el planner-bookmark.el planner-calendar.el planner-cyclic.el planner-deadline.el planner-diary.el planner-el.texi planner-erc.el planner-experimental.el planner-export-diary.el planner-gnats.el planner-gnus.el planner-ical.el planner-id.el planner-ledger.el planner-lisp.el planner-log-edit.el planner-mhe.el planner-multi.el planner-notes-index.el planner-psvn.el planner-publish.el planner-rank.el planner-rdf.el planner-report.el planner-rmail.el planner-rss.el planner-schedule.el planner-tasks-overview.el planner-timeclock-summary-proj.el planner-timeclock-summary.el planner-timeclock.el planner-trunk.el planner-unix-mail.el planner-vm.el planner-w3m.el planner-wl.el planner-xtla.el planner.el 2006-03-06 15:49:19 GMT Jim Ottaway patch-13 Summary: Merged from jeho@jeho.org--2005 (patch 51-53), mwolson@gnu.org--2006-planner-el (patch 13) Revision: planner--main--1.0--patch-16 * planner-appt.el: Revert to the old method of tracking appts added to the schedule. The text property method was simpler, but failed when re-visiting today's plan page [since text properties don't get saved]. (planner-appt-update-appt-section): fix wrong side of bound error (--planner-appt-lines-added-to-section): global variable tracking appts added to the schedule (planner-appt-task-schedule-item-p): use --planner-appt-lines-added-to-section (planner-appt-update-appt-section): revert to the old method (planner-appt-forthcoming-get-appts): fix small bug where an appt schedule item would fall through the conditional and try to be parsed as a task item. modified files: planner-appt.el 2006-02-28 16:49:28 GMT Jim Ottaway patch-12 Summary: Merged from mwolson@gnu.org--2006-planner-el (patch 12) Revision: planner--main--1.0--patch-15 * planner-appt.el (planner-appt-forthcoming-get-appts): Use `insert-file-contents' instead of `insert-file-contents-literally'. modified files: planner-appt.el 2006-02-27 19:38:45 GMT Andrew J. Korty patch-10 Summary: sort status report entries by plan page name Revision: planner-el--devel--0--patch-10 * planner-report.el (planner-report-generate): sort pages by name using string< modified files: planner-report.el 2006-02-27 11:38:48 GMT Jim Ottaway patch-9 Summary: small fix to README file Revision: planner-el--devel--0--patch-9 * README: remove (setq load-path ...) from the load-path example modified files: README 2006-02-27 10:34:20 GMT Jim Ottaway patch-8 Summary: planner-appt: fix highlighting in plan pages Revision: planner-el--devel--0--patch-8 * planner-appt.el (planner-appt-task-highlight): check that a task has today's date modified files: planner-appt.el 2006-02-27 04:46:50 GMT Michael Olson patch-13 Summary: Prepare new Debian package. Revision: planner--main--1.0--patch-13 modified files: Makefile.defs debian/changelog debian/control debian/emacsen-install debian/rules 2006-02-27 04:04:17 GMT Michael Olson patch-12 Summary: Update NEWS and ChangeLog Revision: planner--main--1.0--patch-12 modified files: ChangeLog.2006 NEWS 2006-02-22 01:57:37 GMT Andrew J. Korty patch-7 Summary: only publish dependencies if they haven't already been published Revision: planner-el--devel--0--patch-7 * planner-authz.el (planner-authz-publishing-alist): alist to track published pages and their dependencies (planner-authz-after-markup): if planner-authz-publishing-alist indicates this page has already been published, and here we are publishing it again, the alist must be stale, so we replace it with a single element for this page; otherwise, add an element for this page to the list (planner-authz-after-project-publish): use planner-authz-publishing-alist to determine which dependencies need publishing (planner-authz-republish-dependencies-maybe): add linked pages to planner-authz-publishing-alist as dependencies if they're not already there modified files: planner-authz.el 2006-02-22 01:55:02 GMT Andrew J. Korty patch-6 Summary: consider all of a note's links when building an access list Revision: planner-el--devel--0--patch-6 * planner-authz.el (planner-authz-note-tag): use "categories" attribute modified files: planner-authz.el 2006-02-22 01:48:52 GMT Andrew J. Korty patch-5 Summary: enable multiple links with "categories" attribute Revision: planner-el--devel--0--patch-5 * planner-publish.el (planner-publish-note-tag): enable "categories" attribute, which stores all of a note's links modified files: planner-publish.el 2006-02-15 20:26:25 GMT Andrew J. Korty patch-4 Summary: add planner-multi support to planner-authz Revision: planner-el--devel--0--patch-4 - when multiple pages are linked to a task or note, merge the access lists to the linked pages using a user-specified function - provide intersection and union functions for merging access lists - disable republishing *during* republishing to avoid indefinite recursion modified files: planner-authz.el 2006-02-15 20:12:41 GMT Andrew J. Korty patch-3 Summary: update to work with latest planner-publish.el Revision: planner-el--devel--0--patch-3 - catch up with function name change in planner-publish.el modified files: planner-authz.el 2006-02-14 06:32:23 GMT Michael Olson patch-9 Summary: Use debian/compat to determine debhelper compat level. Revision: planner--main--1.0--patch-9 * debian/compat: New file that sets the debhelper compatibility level to 4. * debian/rules: Remove DH_COMPAT line. new files: debian/.arch-ids/compat.id debian/compat modified files: debian/rules 2006-02-10 22:53:52 GMT Michael Olson patch-8 Summary: Fix Bug #5234: planner-gnus pseudo-article error. Revision: planner--main--1.0--patch-8 * planner-gnus.el (planner-gnus-browse-url): Apply patch from Sacha that should fix Bug #5234: planner-gnus pseudo-article error. modified files: planner-gnus.el 2006-01-30 11:55:00 GMT Jim Ottaway patch-45 Summary: further fix for XEmacs initialization Revision: planner--jeho--1.1--patch-45 * planner-appt.el (planner-appt-insinuate): for XEmacs, create a diary file if one doesn't already exist modified files: planner-appt.el 2006-01-28 10:42:04 GMT Jim Ottaway patch-44 Summary: fix initialization for XEmacs Revision: planner--jeho--1.1--patch-44 * planner-appt.el (planner-appt-insinuate): try to fix initialization for XEmacs: add (display-time). modified files: planner-appt.el 2006-01-26 00:38:24 GMT Michael Olson patch-6 Summary: planner-gnus: Fix buggy browsing behavior. Revision: planner--main--1.0--patch-6 * planner-gnus.el (planner-gnus-browse-url): Prefer to use the `gnus-find-matching-articles' function if it exists. Thanks to John Sullivan for the report. modified files: planner-gnus.el 2006-01-25 12:51:16 GMT Michael Olson patch-5 Summary: Don't insert too many spaces around task number. Revision: planner--main--1.0--patch-5 * planner.el (planner-task-format, planner-format-task): Apply patch from Stefan Reichör that keeps extra spaces from being inserted when planner-use-task-numbers is nil. modified files: planner.el 2006-01-24 02:11:47 GMT Michael Olson patch-4 Summary: planner-calendar: Make a tag. Revision: planner--main--1.0--patch-4 * planner-calendar.el (planner-calendar-insert-calendar-maybe): Insert a tag, rather than using a tag, since we can't yet tell to publish read-only. (planner-calendar-move-calendar-to-top-of-page-maybe): Use planner-insert-markup rather than `insert'. Make sure we can snarf the region safely, even if it is read-only. (planner-publish-calendar-tag): New function that publishes a tag. * planner-publish.el (planner-publish-markup-tags): Docfix. modified files: planner-calendar.el planner-publish.el 2006-01-23 17:22:16 GMT Michael Olson patch-3 Summary: Make planner-visit-link more robust. Revision: planner--main--1.0--patch-3 * planner.el (planner-visit-link): Make this more robust by merging in some changes from Muse. Thanks to Seth Falcon for the sample fix. Among other things, this correctly adds the file extension when visiting a new Muse file. modified files: planner.el 2006-01-21 01:55:13 GMT Michael Olson patch-2 Summary: Debian package refinements. Revision: planner--main--1.0--patch-2 * Makefile (debrevision): New rule that causes a Debian package with a revision to be built. The main difference between this and `debrelease' is that the .orig.tar.gz file is left alone. (debbuild): New rule factored from debrelease. (debclean): Removed, since we use slightly differing variations of this in debrelease and debrevision. * debian/README.Debian: Add comments and my debian repo. * debian/emacsen-install: Make sure we symlink planner-autoloads.el. Thanks to Romain Francoise for noticing. * debian/rules: DTRT with NEWS and README.Debian. modified files: Makefile Makefile.defs debian/README.Debian debian/changelog debian/emacsen-install debian/rules renamed files: debian/.arch-ids/NEWS.Debian.id ==> debian/.arch-ids/NEWS.id debian/NEWS.Debian ==> debian/NEWS 2006-01-19 01:57:47 GMT Michael Olson patch-1 Summary: Debian fixups. Revision: planner--main--1.0--patch-1 * debian/emacsen-startup: Remove unnecessary path addition. * debian/rules: Explicitly install README.Debian and NEWS.Debian. modified files: debian/emacsen-startup debian/rules 2006-01-17 01:16:25 GMT Michael Olson patch-184 Summary: Release Planner 3.40. Revision: planner-muse--mwolson--1.0--patch-184 * planner-el.texi (Installing from a Source Archive) (Installing from Arch, Installing from Debian): Update. modified files: planner-el.texi planner.el 2006-01-17 00:56:42 GMT Michael Olson patch-183 Summary: Update Debian package instructions. Install autoloads. Revision: planner-muse--mwolson--1.0--patch-183 * Makefile (install): Make sure autoloads are installed. * debian/README.Debian: Update. * debian/copyright: Update the Upstream Authors and Copyright sections. * debian/rules: Build autoloads. Install extra files. * debian/emacsen-install (FILES): Filter out autoloads file. * debian/emacsen-startup: Add shared planner-el directory to path. Load autoloads file. * planner-el.texi (Appointment Hooks): Add space after @defvr to fix a syntax error. (Acknowledgements): Add a missing @end itemize. new files: .arch-ids/NEWS.id NEWS debian/.arch-ids/NEWS.Debian.id debian/.arch-ids/planner-el.info.id debian/NEWS.Debian debian/planner-el.info modified files: AUTHORS ChangeLog.2005 ChangeLog.2006 Makefile Makefile.defs README debian/README.Debian debian/changelog debian/copyright debian/emacsen-install debian/emacsen-startup debian/planner-el.docs debian/rules planner-el.texi planner-publish.el planner.el {arch}/planner-muse/planner-muse--mwolson/planner-muse--mwolson--1.0/mwolson@gnu.org--2005/patch-log/patch-35 2006-01-16 17:30:22 GMT Michael Olson patch-182 Summary: Update FSF postal address. Add README. Revision: planner-muse--mwolson--1.0--patch-182 * Update FSF postal address in headers of all Planner source files. * planner-el.texi: Update version information. Use "XEmacs" rather than "Xemacs". (Getting Help): Document the official website and the bug-tracker. (Acknowledgements): Remove list of contributors, since this is contained in AUTHORS. new files: .arch-ids/README.id README modified files: planner-accomplishments.el planner-appt.el planner-authz.el planner-bbdb.el planner-bibtex.el planner-bookmark.el planner-calendar.el planner-cyclic.el planner-deadline.el planner-diary.el planner-el.texi planner-erc.el planner-experimental.el planner-export-diary.el planner-gnats.el planner-gnus.el planner-ical.el planner-id.el planner-ledger.el planner-lisp.el planner-log-edit.el planner-mhe.el planner-multi.el planner-notes-index.el planner-psvn.el planner-publish.el planner-rank.el planner-rdf.el planner-report.el planner-rmail.el planner-rss.el planner-schedule.el planner-tasks-overview.el planner-timeclock-summary-proj.el planner-timeclock-summary.el planner-timeclock.el planner-trunk.el planner-unix-mail.el planner-vm.el planner-w3m.el planner-wl.el planner-xtla.el planner.el 2006-01-15 16:51:31 GMT Michael Olson patch-181 Summary: planner-appt: Handle initialization of the appt system. Revision: planner-muse--mwolson--1.0--patch-181 * planner-appt.el (planner-appt-insinuate): Merged patch from Jim Ottaway that initializes the appt system. * planner-el.texi (Appointments): Remove old kludge. modified files: planner-appt.el planner-el.texi 2006-01-14 00:20:17 GMT Michael Olson patch-180 Summary: planner-gnus: Make browsing Gnus URLs work with Emacs21, hopefully. Revision: planner-muse--mwolson--1.0--patch-180 * planner-gnus.el (planner-gnus-browse-url): Try some ideas from Dale Smith that might make this work with Emacs21. modified files: AUTHORS planner-gnus.el 2006-01-14 00:06:14 GMT Michael Olson patch-179 Summary: Finish copyright notices and AUTHORS file. Revision: planner-muse--mwolson--1.0--patch-179 modified files: AUTHORS ChangeLog.2005 planner-appt.el planner-authz.el planner-bbdb.el planner-bibtex.el planner-calendar.el planner-deadline.el planner-diary.el planner-export-diary.el planner-id.el planner-ledger.el planner-log-edit.el planner-mhe.el planner-multi.el planner-notes-index.el planner-psvn.el planner-publish.el planner-report.el planner-tasks-overview.el planner-unix-mail.el planner.el 2006-01-13 17:00:44 GMT Michael Olson patch-178 Summary: Progress: planner.el (2005) Revision: planner-muse--mwolson--1.0--patch-178 modified files: AUTHORS planner-rmail.el planner-rss.el planner-schedule.el planner-tasks-overview.el planner-timeclock-summary-proj.el planner-timeclock-summary.el planner-timeclock.el planner-trunk.el planner-unix-mail.el planner-vm.el planner-w3m.el planner-wl.el planner-xtla.el planner.el planner2diary.py 2006-01-12 16:32:51 GMT Michael Olson patch-177 Summary: Progress: planner-rmail.el Revision: planner-muse--mwolson--1.0--patch-177 modified files: AUTHORS planner-el.texi planner-multi.el planner-notes-index.el planner-psvn.el planner-publish.el planner-rank.el planner-rdf.el planner-report.el 2006-01-11 10:43:30 GMT Jim Ottaway patch-40 Summary: planner.el: excessive highlighting Revision: planner--jeho--1.1--patch-40 * planner.el (with-planner-update-setup): remove highlight inhibition to see whether the problem is really with planner-mode (planner-mode): don't explicitly call muse-colors-buffer modified files: planner.el 2006-01-11 01:40:40 GMT Michael Olson patch-174 Summary: Progress: planner-multi.el Revision: planner-muse--mwolson--1.0--patch-174 modified files: AUTHORS ChangeLog.2005 planner-id.el planner-ledger.el planner-lisp.el planner-log-edit.el planner-mhe.el planner-multi.el 2006-01-11 01:28:32 GMT Peter K. Lee patch-17 Summary: (planner-publish.el) properly derives "xml" to form "planner-xml" style! Revision: planner-muse--peter--1.0--patch-17 * planner-publish.el (muse-xml): add require for 'muse-xml (planner-xml-extension): no longer needed since 'muse-xml-extension exists. (planner-publish-markup-tags): changed to nested-section and tasks-section to match notes-section precedent. (planner-xml-markup-strings): revamped to behave similar to `planner-html-markup-strings' (planner-xml-header): mimics `muse-xml-header', but the root element is PLANNER not MUSE. (planner-html-markup-strings): resort to using the TITLE tag to generate static html code, instead of using H2, H3, etc. like before. (planner-html-style-sheet): added some defaults for nested .section .title style differentiation. (planner-publish-markup-note): there's no LEVEL in TITLE anymore. (planner-publish-nested-section-tag): naming changes (planner-publish-title-tag): simplify title tag generation. use a static markup string, instead of drawing from 'section, 'subsection variables. The reason for this change, although I _did_ like the former behavior of using H2, H3, etc. for HTML markup is that the 'section, 'subsection variables of muse-xml do NOT behave the same way as muse-html does (where muse-html acts more like just a title). (sectionalize): generate title tag w/o LEVEL attribute. (muse-derive-style): the REAL reason for all the changes above! Now planner-publish takes in the new muse-xml style and derives a new planner specific style, "planner-xml" style. modified files: planner-publish.el 2006-01-10 21:47:47 GMT Jim Ottaway patch-38 Summary: with-planner-update-setup: fix typo Revision: planner--jeho--1.1--patch-38 modified files: planner.el 2006-01-09 17:19:23 GMT Michael Olson patch-173 Summary: More copyright twiddling. Progress: planner-ical.el Revision: planner-muse--mwolson--1.0--patch-173 modified files: AUTHORS ChangeLog.2004 planner-accomplishments.el planner-appt.el planner-bbdb.el planner-bibtex.el planner-calendar.el planner-cyclic.el planner-deadline.el planner-diary.el planner-erc.el planner-experimental.el planner-export-diary.el planner-gnats.el planner-gnus.el 2006-01-09 13:32:58 GMT Michael Olson patch-172 Summary: Fix some more copyright headers. Revision: planner-muse--mwolson--1.0--patch-172 modified files: AUTHORS planner-el.texi planner-erc.el planner-xtla.el 2006-01-09 02:34:36 GMT Michael Olson patch-171 Summary: Edit more copyright notices. Add AUTHORS. Revision: planner-muse--mwolson--1.0--patch-171 * AUTHORS: New file containing a thorough listing of contributors and authors of Planner, its documentation, and its modules. I'm about half-way done verifying its contents. new files: .arch-ids/AUTHORS.id AUTHORS modified files: ChangeLog.2005 planner-authz.el planner-bbdb.el planner-bibtex.el planner-bookmark.el planner-calendar.el planner-cyclic.el planner-deadline.el planner-diary.el planner-el.texi planner-multi.el planner-xtla.el planner.el 2006-01-09 01:08:14 GMT Michael Olson patch-170 Summary: Fix delegated task errors. Work on updating copyright statements. Revision: planner-muse--mwolson--1.0--patch-170 * planner-publish.el (planner-publish-markup-regexps): Change ">" to "D" for delegated mark. Thanks to Seth Falcon for the report. * planner-rank.el (planner-sort-tasks-by-rank) (planner-sort-tasks-by-importance, planner-sort-tasks-by-urgency): Ditto. * planner-rdf.el (planner-rdf-matchstr-ptask): Ditto. * planner.el (planner-marks-regexp, planner-live-task-regexp): (planner-sort-tasks-basic, planner-seek-next-unfinished-task): Ditto. * planner.el (planner-version): Set to 3.39. modified files: ChangeLog.2004 ChangeLog.2005 planner-accomplishments.el planner-appt.el planner-authz.el planner-calendar.el planner-deadline.el planner-experimental.el planner-publish.el planner-rank.el planner-rdf.el planner.el renamed files: .arch-ids/PLANNER-README.id ==> .arch-ids/COMMENTARY.id PLANNER-README ==> COMMENTARY 2006-01-08 21:51:19 GMT Michael Olson patch-169 Summary: Complete writing of ChangeLogs. Revision: planner-muse--mwolson--1.0--patch-169 * ChangeLog.2004, ChangeLog.2005, ChangeLog.2006: Complete the merging of other logs and removal of "merged this" logs. modified files: ChangeLog.2004 ChangeLog.2005 ChangeLog.2006 2006-01-08 04:54:05 GMT Michael Olson patch-168 Summary: Add ChangeLogs from contributors. Revision: planner-muse--mwolson--1.0--patch-168 Remove a few emacs-wiki-only changelogs. * ChangeLog.2004, ChangeLog.2005: Add ChangeLog entries of contributors. This is not complete yet. modified files: ChangeLog.2004 ChangeLog.2005 2006-01-07 06:02:30 GMT Michael Olson patch-167 Summary: Update Makefile, split ChangeLog. Revision: planner-muse--mwolson--1.0--patch-167 * Makefile (release): Create GPG keys here instead of at upload time. * ChangeLog: Refactor into ChangeLog.2004-2006. We'll just manually merge in entries at release time, I guess. It might be good to get the full logs from merged sources, too. new files: .arch-ids/ChangeLog.2004.id .arch-ids/ChangeLog.2005.id .arch-ids/ChangeLog.2006.id ChangeLog.2004 ChangeLog.2005 ChangeLog.2006 removed files: .arch-ids/ChangeLog.id ChangeLog modified files: Makefile Makefile.defs 2006-01-06 20:21:25 GMT Michael Olson patch-166 Summary: XEmacs fixes. Revision: planner-muse--mwolson--1.0--patch-166 * planner-appt.el (planner-appt-add-appts-from-tasks): Remove unused obsolete variable. * planner-authz.el (planner-authz-mason-markup-table): (planner-authz-diary-tag): Use planner-line-beginning-position. * planner-el.texi (Appointments): Add code snippet for activating appt.el. * planner-mhe.el: Require mh-index. * planner-rmail.el (planner-rmail-narrow-to-non-pruned-header): New function that provides an implementation of rmail-narrow-to-non-pruned-header, since XEmacs lacks it. (planner-rmail-annotation-from-mail): Use planner-rmail-narrow-to-non-pruned-header. * planner.el: Wrap conditional `require' in `eval-when-compile'. modified files: ChangeLog planner-appt.el planner-authz.el planner-el.texi planner-mhe.el planner-rmail.el planner.el 2006-01-06 19:53:00 GMT Michael Olson patch-165 Summary: planner-appt: XEmacs fix. Revision: planner-muse--mwolson--1.0--patch-165 * Makefile.defs: Fix typo. * planner-appt.el: Add usage instructions which mention how to activate appt. (planner-appt-update-appt-section): Don't use `propertize', since XEmacs doesn't have it. modified files: ChangeLog Makefile.defs planner-appt.el 2006-01-06 02:44:17 GMT Michael Olson patch-164 Summary: Massively clean whitespace and fix compiler warnings. Revision: planner-muse--mwolson--1.0--patch-164 modified files: ChangeLog planner-appt.el planner-bibtex.el planner-calendar.el planner-diary.el planner-export-diary.el planner-gnus.el planner-ical.el planner-rank.el planner-report.el planner-rss.el planner-tasks-overview.el planner.el scripts/planner-build.el 2006-01-06 01:45:10 GMT Michael Olson patch-163 Summary: planner-el.texi: Fix a few URL examples. Revision: planner-muse--mwolson--1.0--patch-163 * planner-el.texi (Emacs Relay Chat): Use "irc://" instead of "erc://" in the examples. (BibTeX): Remove the initial forward-slashes from the sample bibtex URL. Thanks to Stefan van der Walt for the report. modified files: ChangeLog planner-el.texi 2006-01-06 01:31:53 GMT Michael Olson patch-162 Summary: planner-accomplishments: Use simpler method of determining hook to use. Revision: planner-muse--mwolson--1.0--patch-162 * planner-accomplishments.el (planner-accomplishments-insinuate): Simplify. This should fix an issue reported by Stefan van der Walt. modified files: ChangeLog planner-accomplishments.el 2006-01-06 01:05:08 GMT Michael Olson patch-161 Summary: Fix an extra-tasks problem in planner-tasks-overview. Revision: planner-muse--mwolson--1.0--patch-161 * planner.el (planner-list-daily-files): Prevent temp buffers from being added when an existing buffer with the same name exists. Thanks to Stefan van der Walt for the report. This should prevent task lists from being doubled in planner-tasks-overview. modified files: ChangeLog planner.el 2006-01-06 00:04:07 GMT Michael Olson patch-160 Summary: Fix documentation example that I wrote earlier. Revision: planner-muse--mwolson--1.0--patch-160 * Makefile.defs: In this intermediate stage, we'll call it Planner 3.39. Replace "planner-muse" with "planner". * debian/changelog: Condense old planner-muse-el entries into a new planner-el entry. * debian/control, debian/emacsen-install, debian/emacsen-remove, emacsen-startup: s/planner-muse-el/planner-muse/. * debian/rules: Use DH_COMPAT=4, since that was the most recent piece of advice from my sponsor. * planner-el.texi (Viewing Tasks): Adjust whitespace. (Publishing): Use an example that has a better chance of working. Thanks to Stefan van der Walt for the report. modified files: ChangeLog Makefile.defs debian/changelog debian/control debian/emacsen-install debian/emacsen-remove debian/emacsen-startup debian/rules planner-el.texi 2006-01-05 23:13:39 GMT Michael Olson patch-159 Summary: Fix emacs-wiki Bug #14907. Revision: planner-muse--mwolson--1.0--patch-159 * planner.el (planner-extract-tasks): Fix backtrace. This also fixes #14907 on the emacs-wiki bug-tracker. modified files: ChangeLog planner.el 2006-01-05 22:23:39 GMT Michael Olson patch-158 Summary: planner-el.texi: Task numbers are not displayed by default. Revision: planner-muse--mwolson--1.0--patch-158 * planner-el.texi (Viewing Tasks): Note that by default, task numbers will not be displayed. Explain how to get them. Thanks to Stefan van der Walt for the report. modified files: ChangeLog planner-el.texi 2006-01-04 00:31:10 GMT John Sullivan patch-5 Summary: Added example and instructions for setting up a new Planner project. Revision: planner-muse--johnsu01--1.0--patch-5 modified files: planner-el.texi 2006-01-03 23:28:18 GMT John Sullivan patch-4 Summary: Fixed name of Debian package and instructions for installing the package. Revision: planner-muse--johnsu01--1.0--patch-4 modified files: planner-el.texi 2006-01-03 22:26:15 GMT Michael Olson patch-155 Summary: Yet Another paragraph detection try. Revision: planner-muse--mwolson--1.0--patch-155 * planner-publish.el (planner-publish-markup-note): Put the newlines in a different spot. (planner-publish-content-tag): Be a bit more delicate about where we insert the markup. modified files: ChangeLog planner-publish.el 2006-01-03 21:19:13 GMT Michael Olson patch-154 Summary: Makefile: Fix argument for install-info. Revision: planner-muse--mwolson--1.0--patch-154 * Makefile (install): Give install-info the correct path. Thanks to Dale Smith for reporting this. modified files: ChangeLog Makefile 2006-01-03 21:14:52 GMT Michael Olson patch-153 Summary: Use "D" to indicate delegated tasks, instead of ">". Revision: planner-muse--mwolson--1.0--patch-153 * planner-accomplishments.el (planner-accomplishments-status-display): Use "D" to indicate delegated tasks, instead of ">". * planner-el.texi (Modifying Tasks): Ditto. * planner-publish.el (planner-publish-task-status-expand): (planner-publish-task-status-collapse): Ditto. * planner-tasks-overview.el (planner-tasks-overview-sort-by-status): Ditto. * planner.el (planner-sort-tasks-by-link, planner-highlight-tasks): (planner-task-delegated): Ditto. modified files: ChangeLog planner-accomplishments.el planner-el.texi planner-publish.el planner-tasks-overview.el planner.el 2006-01-03 19:36:56 GMT Michael Olson patch-152 Summary: Fix double-escaping issue. Revision: planner-muse--mwolson--1.0--patch-152 * Makefile (install): Install the manual as "planner", not "planner-muse". * Makefile.defs (ELISPDIR): Install the elisp files to site-lisp/planner rather than site-lisp/planner-muse. * planner-publish.el (planner-publish-markup-note): Apply patch from Dale Smith that fixes a double-escaping of specials with muse--main. (planner-publish-section-tag): Revert a previous whitespace patch. (planner-publish-content-tag): Insert an additional newline. Hopefully this finally fixes the paragraph detection problem. modified files: ChangeLog Makefile Makefile.defs planner-publish.el 2006-01-03 01:40:44 GMT Andrew J. Korty patch-14 Summary: don't insert task number padding if planner-use-task-numbers is nil Revision: planner-muse--main--1.0--patch-14 modified files: planner.el 2006-01-03 01:32:10 GMT John Sullivan patch-3 Summary: Updated maintainer information. Removed distinction between stable and development versions. Distributed the Updating Your Version node information and removed it. Made new nodes for each installation method under a new Getting the Files section. Revision: planner-muse--johnsu01--1.0--patch-3 modified files: planner-el.texi 2006-01-03 00:32:40 GMT Michael Olson patch-150 Summary: muse-publish: Try again to fix paragraph detection. Revision: planner-muse--mwolson--1.0--patch-150 * planner-publish.el (planner-publish-content-tag): Insert an extra newline. modified files: ChangeLog planner-publish.el 2006-01-02 23:31:02 GMT Michael Olson patch-149 Summary: planner-publish: Try to fix paragraph error. Revision: planner-muse--mwolson--1.0--patch-149 * planner-publish.el (planner-publish-section-tag): Attempt to fix a paragraph markup error. modified files: ChangeLog planner-publish.el 2006-01-02 22:54:03 GMT Michael Olson patch-148 Summary: planner-publish: Remove extra tag. Revision: planner-muse--mwolson--1.0--patch-148 * planner-publish.el (planner-html-markup-strings): Apply patch from Dale Smith that removes a stray tag. modified files: ChangeLog planner-publish.el 2006-01-02 22:48:38 GMT Michael Olson patch-147 Summary: planner-publish: Yet Another Patch. Remove stale functions. Revision: planner-muse--mwolson--1.0--patch-147 * planner-appt.el (planner-appt-de-wiki): Move to planner.el. (planner-appt-format-description): Use planner-remove-links rather than planner-appt-de-wiki. * planner-publish.el: Apply patch from Dale Smith. (planner-publish-markup-tags): Use the correct attributes. (planner-publish-notes-section-tag): Don't call muse-publish-markup-region explicitly. * planner-publish.el (planner-publish-notes-tag): Use planner-remove-links. * planner.el (planner-encode-url, planner-link-escape) (planner-link-unescape): Remove. (planner-remove-links): Renamed from planner-appt-de-wiki. Keep track of start position for sanity. modified files: ChangeLog planner-appt.el planner-publish.el planner.el 2006-01-02 21:15:28 GMT Michael Olson patch-146 Summary: planner-publish: Work further on and tags. Revision: planner-muse--mwolson--1.0--patch-146 * planner-publish.el (planner-html-markup-strings): Split planner-note-details into manageable chunks. (planner-publish-markup-note, planner-publish-notes-section-tag): s/notes/notes-section/. Thanks to Dale Smith for the patch. (planner-publish-past-notes-tag): Fix the name of this function, thanks to Dale Smith. Make it use planner-insert-markup in some parts so that raw HTML doesn't get escaped. (planner-publish-note-tag): Split up the 'planner-note-details string so that we can be selective about the parts that are marked up as read-only. modified files: ChangeLog planner-publish.el 2006-01-02 19:15:06 GMT Michael Olson patch-145 Summary: planner-publish: Make "* Notes" section publish correctly again. Revision: planner-muse--mwolson--1.0--patch-145 * planner-publish.el: Re-add the planner-publish-notes-tag function, but rename to planner-publish-notes-section. emacs-wiki had the tag insert an index of notes, so we'll use that as the behavior of . We still need the other function, though, to publish the "* Notes" section. Thanks to Dale Smith for the advice. (planner-publish-markup-tags): Add notes-section tag (planner-publish-notes-section-tag): Renamed from the old planner-publish-notes-tag function. (sectionalize-markup-tagname): Mark up "* Notes" section as "notes-section" instead of "notes". modified files: ChangeLog planner-publish.el 2006-01-01 22:58:59 GMT Michael Olson patch-144 Summary: Apply several bugfixes from Sacha. Revision: planner-muse--mwolson--1.0--patch-144 * planner-rss.el (planner-publish-markup-rss-functions): Fix typo. Thanks to Sacha Chua for the fix. * planner.el (planner-jump-to-linked-note): Delete only occurs on linked page if narrowing succeeds. The previous behavior was to delete entire linked page if linked note wasn't found. Thanks to Lee Bigelow and Sacha Chua for the fix. modified files: ChangeLog planner-rss.el planner.el See ChangeLog.2 for earlier changes. ;; Local Variables: ;; coding: utf-8 ;; End: planner-el/Makefile000066400000000000000000000057031226462314700145670ustar00rootroot00000000000000.PHONY: all autoloads lisp doc clean realclean distclean fullclean install .PHONY: test dist release upload elpa info-only .PRECIOUS: %.elc DEFS = $(shell test -f Makefile.defs && echo Makefile.defs \ || echo Makefile.defs.default) include $(DEFS) EL = $(filter-out $(PROJECT)-autoloads.el,$(wildcard *.el)) ELC = $(patsubst %.el,%.elc,$(EL)) all: autoloads lisp $(MANUAL).info lisp: $(ELC) $(PROJECT)-build.elc: ./scripts/$(PROJECT)-build.el @echo $(PROJECT)-build.el is not byte-compiled autoloads: $(PROJECT)-autoloads.el $(PROJECT)-autoloads.el: $(EL) @$(EMACS) -q $(SITEFLAG) -batch -l ./scripts/$(PROJECT)-build.el \ -f $(PROJECT)-generate-autoloads . contrib %.elc: %.el @$(EMACS) -q $(SITEFLAG) -batch -l ./scripts/$(PROJECT)-build.el \ -f batch-byte-compile $< || : %.info: %.texi makeinfo $< %.html: %.texi makeinfo --html --no-split $< info-only: $(MANUAL).info doc: $(MANUAL).info $(MANUAL).html clean: -rm -f *.elc *~ realclean fullclean: clean -rm -f $(MANUAL).info $(MANUAL).html $(PROJECT)-autoloads.el install: autoloads lisp $(MANUAL).info install -d $(ELISPDIR) install -m 0644 $(PROJECT)-autoloads.el $(EL) $(wildcard *.elc) \ $(ELISPDIR) [ -d $(INFODIR) ] || install -d $(INFODIR) install -m 0644 $(MANUAL).info $(INFODIR)/$(MANUAL) $(call install_info,$(MANUAL)) test: $(ELC) $(EMACS) -q $(SITEFLAG) -batch -l ./scripts/$(PROJECT)-build.el \ -f $(PROJECT)-elint-files $(EL) distclean: -rm -f $(MANUAL).info $(MANUAL).html -rm -fr ../$(PROJECT)-$(VERSION) dist: autoloads distclean git archive --format=tar --prefix=$(PROJECT)-$(VERSION)/ HEAD | \ (cd .. && tar xf -) rm -f ../$(PROJECT)-$(VERSION)/.gitignore rm -fr ../$(PROJECT)-$(VERSION)/test cp $(PROJECT)-autoloads.el ../$(PROJECT)-$(VERSION)/lisp release: dist (cd .. && tar -czf $(PROJECT)-$(VERSION).tar.gz \ $(PROJECT)-$(VERSION) && \ zip -r $(PROJECT)-$(VERSION).zip $(PROJECT)-$(VERSION) && \ gpg --detach $(PROJECT)-$(VERSION).tar.gz && \ gpg --detach $(PROJECT)-$(VERSION).zip) upload: release (cd .. && \ scp $(PROJECT)-$(VERSION).zip* $(PROJECT)-$(VERSION).tar.gz* \ johnsu01@download.gna.org:/upload/planner-el) elpa: realclean info-only rm -fR $(ELPADIR)/$(PROJECT)-$(VERSION) rm -f $(ELPADIR)/$(PROJECT)-$(VERSION).tar mkdir -p $(ELPADIR)/$(PROJECT)-$(VERSION) cp *.el $(ELPADIR)/$(PROJECT)-$(VERSION) cp contrib/*.el $(ELPADIR)/$(PROJECT)-$(VERSION) echo '(define-package "$(PROJECT)" "$(VERSION)"' > \ $(ELPADIR)/$(PROJECT)-$(VERSION)/$(PROJECT)-pkg.el echo ' "$(ELPADESC)")' >> \ $(ELPADIR)/$(PROJECT)-$(VERSION)/$(PROJECT)-pkg.el cp texi/$(MANUAL).info $(ELPADIR)/$(PROJECT)-$(VERSION) cp texi/dir-template $(ELPADIR)/$(PROJECT)-$(VERSION)/dir install-info --section "Emacs" "Emacs" \ --info-dir=$(ELPADIR)/$(PROJECT)-$(VERSION) \ $(ELPADIR)/$(PROJECT)-$(VERSION)/$(MANUAL).info rm -f $(ELPADIR)/$(PROJECT)-$(VERSION)/dir.old (cd $(ELPADIR) && tar cf $(PROJECT)-$(VERSION).tar \ $(PROJECT)-$(VERSION)) planner-el/Makefile.defs.default000066400000000000000000000023131226462314700171240ustar00rootroot00000000000000# -*- Makefile -*- # # If you wish to modify this file, first copy it to a file called # Makefile.defs. The resulting Makefile.defs file may then be # modified. # Emacs options EMACS = emacs SITEFLAG = --no-site-file # XEmacs users will probably want the following settings. #EMACS = xemacs #SITEFLAG = -no-site-file # Installation options # PREFIX is only used here. PREFIX = /usr/local ELISPDIR = $(PREFIX)/share/emacs/site-lisp/planner INFODIR = $(PREFIX)/info # Command to use to install the Info dir entry install_info = install-info --info-dir=$(INFODIR) $(1) || : # If you're using Debian or Ubuntu, uncomment the following rule and # comment out the previous rule. # #install_info = install-info --section "Emacs" "emacs" --info-dir=$(INFODIR) \ # $(INFODIR)/$(1) || : # If you're using XEmacs, use something like the following instead of # the above two rules. # #install_info = install-info --section "XEmacs 21.4" $(1).info \ # $(INFODIR)/dir || : # Useful only for the maintainer PROJECT = planner DEBNAME = planner-el VERSION = 3.42 MANUAL = planner-el # Location of Emacs Lisp Package Archive entries ELPADIR = ../../elpa # Description of ELPA package ELPADESC = The Emacs Planner planner-el/NEWS000066400000000000000000000371741226462314700136350ustar00rootroot00000000000000Planner NEWS --- History of user-visible changes -*- outline -*- * Changes in Planner 3.42 With this version, Planner is now available under GPLv3 (or any later version published by the Free Software Foundation). Planner now requires Muse 3.03 or later. ** Bugfixes *** planner: Note searching was returning bits of neighboring notes in search results. When moving blocks of tasks, don't include the task at the beginning of the region if point is at the end of the line, but do include it otherwise. *** planner-appt: Fix interaction with planner-deadline and task-based appointments. Fix match-string bug. *** planner-authz: Adapt for nested tag support. Fix markup for diary sections. *** planner-calendar: Adapt for nested tag support. Handle situation where the calendar for the next month is empty. *** planner-el.texi: Many updates and corrections. *** planner-gnus: Fix problem where unread messages were marked as read. Make documented keybindings actually work. *** planner-mhe: Remove unnecessary dependency. *** planner-notes-index: Muse compatibility fixes. *** planner-publish: Publish task IDs. Fix calendar publishing. Adapt for nested tag support. Fix escaping issues. *** planner-report: Handle non-ASCII characters. *** planner-rss: Markup was incorrectly being escaped. *** planner-tasks-overview: Make returned links work, and improve display. *** planner-timeclock: Don't require project match. Muse compatibility fixes. *** planner-wl: Change keybinding to C-c from C-t, to avoid collision. *** planner-zoom: Use planner-page-name instead of buffer-name. *** README: Grammar fixes and other updates. *** timeclock: Better support for encrypted timeclock files. ** Compatibility fixes *** planner: Update to work with Emacs 22. Fix to work with ntemacs 23.0.0.1. *** planner-gnus: Fix to work with No Gnus and Gnus 5.11. *** planner-ledger: Update to work with newer versions of ledger. *** planner-publish: Fix XEmacs bugs. *** planner-timeclock: Remove unnecessary dependency. ** New features *** Makefile: Make ELPA package. New rule to make just the info file. Update for git. *** planner: Add hook to task deletion. Pick up annotation from man and woman pages. *** planner-gnus: Support gnuslog URLs. *** planner-ledger: Add customize interface. The user can now specify a ledger file. Add a number of new functions for cleanly inserting ledger info into Planner pages. * Changes in Planner 3.41 ** Bugfixes *** Make planner-visit-link more robust. *** Don't insert too many spaces around task number. *** Fix lock up with old delegated task mark. *** Make allout mode and Planner work better together by default. *** planner-el.texi: Many updates and clarifications were added. *** planner-appt: Fix highlighting in plan pages. *** planner-authz: Work with latest changes in planner-publish. *** planner-calendar: Fix many bugs and improve implementation. Be sure to read the "Publishing Calendars" section of the manual for details, as the common setup for Planner 3.40 will not work. This feature should now be much easier to get working. *** planner-calendar: If the current page is not a daypage, default to publishing a calendar for today. *** planner-gnus: Fix buggy browsing behavior. *** planner-publish: Fix erroneous output at end of file. ** Compatibility fixes *** planner-appt: Fix initialization for XEmacs. *** planner-appt: For XEmacs, create a diary file if one does not exist. *** planner-erc: Work with newer versions of ERC. *** planner-psvn: Make this work with newer versions of psvn.el. ** New features *** Display a helpful message if muse-project-alist is undefined. *** New function `planner-tomorrow' returns the date for tomorrow. *** planner-appt: New option `planner-appt-forthcoming-show-day-names-flag' that indicates whether to show day names in forthcoming appointments. *** planner-authz: Add planner-multi support. *** planner-authz: Consider all of a note's links when building an access list. *** planner-authz: Only publish dependencies if they haven't already been published. *** planner-authz: Improve list handling. *** planner-calendar: Make a tag. *** planner-calendar: Surround generated calendar with
    tag. *** planner-erc: Connect to an existing chat session when following a link, if possible. *** planner-id: Remove task IDs when publishing. *** planner-publish: Enable multiple links with "categories" attribute. *** planner-publish: Use

    ,

    , etc. for headings. *** planner-publish: Add default CSS elements for calendar, notes, and diary sections. *** planner-publish: Preserve line breaks when publishing diary section. *** planner-report: Sort pages by plan page name. ** New files *** planner-registry.el: Registry of URLs and Planner annotations. *** planner-zoom.el: Navigate plan pages. * Changes in Planner 3.40 ** Migration to Muse backend from emacs-wiki is complete. Planner is now based on Emacs Muse, rather than emacs-wiki. This will require a few changes to your Planner configuration. See the `Creating Your Planner' section of the Planner manual for an example Planner and Muse configuration. Other considerations follow. *** WikiNames are not colorized by default. If you want WikiName support, add a "(require 'muse-wiki)" line to your Planner configuration. *** List items that that begin with "- " should begin with " - ". *** The use of `planner-option-customized' is deprecated. Please change any use of `planner-option-customized' to `setq' in your configuration. Most of the options that required this no longer exist. *** Planner files must have a .muse extension. Make sure that you rename your Planner files to have a ".muse" extension, or they will not be recognized. *** Publishing may be done by means of the planner-publish.el file. Add "(require 'planner-publish)" to your Planner configuration to use it. This will make available several publishing styles that you can use with `muse-project-alist'. The difference between planner-specific publishing styles and the normal Muse publishing styles is that the former can mark up tasks and notes specially. ** New files *** AUTHORS: List of contributors to Planner and authors of Planner files. *** ChangeLog.2004, ChangeLog.2005, ChangeLog: A fairly complete history of changes to Planner since January 2004. *** COMMENTARY: John Wiegley's original Planner commentary, moved from PLANNER-README. *** NEWS: This file, which lists user-visible changes since Planner 3.28. *** Makefile, Makefile.defs, scripts/planner-build.el: A simple build system for Planner. *** README: Instructions for building and installing Planner. ** Compatibility *** Browsing Gnus URLs should work with Emacs21. *** Several XEmacs fixes were committed. ** Misc *** Change of Delegated mark from ">" to "D". Make sure that you use "D" instead of ">" to indicate delegated tasks, or these tasks will not display or publish properly. *** planner-accomplishments: Line up accomplishments neatly. *** planner-appt: Forthcoming appointments are now dealt with. *** planner-authz: Several TODO items were completed. *** planner-deadline: New `add' and `remove' functions. *** planner-multi: New option `planner-multi-date-links-last-p' indicates whether to put date links after links to other pages. *** planner-rss: Some options might not be backwards-compatible. *** planner-timeclock-summary-proj: Several enhancements were made. *** planner.el **** Don't insert task padding if `planner-use-task-numbers' is nil. **** Shortened dates like "2005.1.6" work. **** When no day pages are desired, more things work than before. **** planner-initial-page: New option that determines which page to visit by default when not using day pages. **** Permit links to buffer names. * Changes in Planner 3.31 ** New or noteworthy *** dev/402: New: Provide planner-log-edit like functionality for xtla *** dev/403: New: planner-delete-section[-text], add CREATE to planner-narrow-to-section *** dev/411: New: planner-mark-task-hook *** dev/417,418: New: planner-multi-copy-tasks-to-page *** dev/420: planner-annotation-as-kill: New interactive prefix *** dev/421: New: planner-annotation-from-file-with-position *** dev/430: planner-update-task: Remove need for advice, planner-multi-replan-task: Accept list as argument *** dev/431: NOTE: planner-create-note: Default to current page *** dev/432: New: planner-gnats.el adds support for the GNU bugtracking system *** dev/446: NOTE: planner-gnus-insinuate: Change keybinding to C-c C-t *** dev/448: Add p-create-task and p-create-task-from-buffer to planner-auto *** dev/456: New: planner-ical.el exports tasks as iCal *** dev/466: NOTE: planner-create-section-function, planner-create-at-top, planner-create-at-bottom: RENAMED FROM planner-seek- ** Bugfix *** dev/404: planner-delete-note actually works now, and planner-rss recognizes categories *** dev/405: Allow arbitrary extensions by using emacs-wiki-page-name *** dev/406,407: planner-appt-add-appts-from-schedule and empty schedules *** dev/408: planner-tasks-overview-get-summary: Work with files in subdirectories *** dev/409: Use write-file-hooks *** dev/412: planner-current-note-info should work with notes with parens *** dev/414: planner-narrow-to-note should recognize more notes properly now *** dev/415: Override planner-task-plan for planner-multi *** dev/416: Do everything inside with-planner-update-setup *** dev/422: planner-annotation-from-file-with-position: Check if buffer has a file *** dev/423: planner-browse-position-url: Do not clobber match data *** dev/424: planner-gnus-browse-url and long grou pnames *** dev/425: with-planner-update-setup, planner-browse-position-url, planner-multi-tasks-equal-p *** dev/426: with-planner-update-setup: Don't block planner-id *** dev/428: planner-annotation-as-kill: Make sure link is set *** dev/429: planner-appt: Merge bugfix for duplicate appt bug *** dev/432: planner-edit-task-description, planner-deadline: keep point *** dev/433: Remove parens around planner-calendar-html-tag-marker *** dev/434: planner-sort-tasks: Be paranoid about task sorting *** dev/436: planner-multi-tasks-equal-p: Deal with tasks without link text *** dev/437: planner-derived-mode-p should pass the modes to derived-mode-p *** dev/438: planner-update-wiki-project: planner-name-regexp fix, planner-save-buffers SKIP-BUFFERS *** dev/439: planner-lower-task: typo *** dev/440: Fixes planner-timeclock + planner-multi, also planner-multi-update-task *** dev/441: planner-save-buffers should suppress planner-id *** dev/442: planner-save-buffers: Do not kill non-planner-mode buffers *** dev/444: planner-multi-replan-task: Deal with tasks without dates *** dev/445: planner-multi-link-delete: Preserve order *** dev/447: planner-calendar-create-today-link: Quote shell arguments *** dev/449: planner-calendar-create-today-link: Use make-symbolic-link *** dev/450: planner-current-note-info: Be stricter with note links *** dev/451: planner-timeclock-summary-make-text-table-day: Format projects as links *** dev/452: Add autoload cookies to a bunch of files, remove planner-appt-filename-to-date *** dev/454: Merge patch to make note heading face less greedy *** dev/455: planner-rss-add-note: Remove tags from title *** dev/459: planner-calendar: Do not over-pad months that end with Sunday *** dev/460: planner-calendar-published-file-href: Stop refreshing the file list all the time *** dev/461: planner-visit-link: Add missing alias *** dev/462: Add missing planner-link-target. New option: planner-calendar-nop-buttons-flag *** dev/463: planner-current-note-info: Recognize multi properly again *** dev/464: Bugfixes: Byte-compile properly (missing planner-link-name, bug in planner-annotation-from-file) *** dev/465: planner-notes-index: Fix to work with files in subdirectories *** dev/467: planner-timeclock should always work within Planner context to properly deal with some tasks *** dev/468: planner-notes-index should be in Planner project *** dev/469: planner-deadline bugfix: Avoid infinite loops by calculating deadlines as we insert them *** dev/470: planner-save-buffers: Check if buffer is associated with a file *** dev/471: with-planner: Defer evaluation of planner-derived-mode-p *** dev/472: with-planner-update-setup: Save current window point as well *** dev/474: planner-appt-mark-calendar shouldn't call planner-appt-filename-to-date ** Docfixes *** dev/412: Reorganize Tasks section (johnsu01/13) *** dev/419: Note that Lisp tags work only for GNU Emacs *** dev/457: Fix iCal example quotes * Changes in Planner 3.30 ** Bugfixes *** dev/382: XEmacs: condition-case instead of 4-arg require, menu *** dev/385: Make planner-sort-tasks stop causing backtraces *** dev/386: planner-replan-note should properly add notes to non-wiki-named pages *** dev/387: planner-gnus-browse-url: Load group even if registry is not used *** dev/389: planner-sort-tasks should use 5-arg sort-subr for older GNU Emacs *** dev/390: planner-sort-tasks: Remove non-fontification code *** dev/392: planner-list-tasks-with-status: Fix insert-file-contents(nil) backtrace *** dev/397: planner-bibtex-regexp: Fix typo. planner-el.texi: Add note about allout.el *** dev/399: planner-extract-tasks: Accept list of pages *** dev/395: planner-list-tasks-with-status bugfix: Deal with undated tasks; do not touch planner-task-format ** Tweaks *** dev/381: planner-vm: Turn on annotations in vm-presentation-mode *** dev/383: planner-multi-read-name-multiple-prompts: Easier multiple inputs *** dev/384: Improve support for putting files in subdirectories *** dev/388: Tweak: planner-copy-or-move-region does not include last line if at start of line *** dev/391: sync with jeho/61-68: planner-appt updates. *** dev/393: planner-list-tasks-with-status: Put an insane amount of meaning into a PAGES argument *** dev/394: planner-list-unfinished-tasks: Add PAGES argument ** New *** dev/400: planner-lisp: Allow arbitrary Lisp expressions *** dev/396: NOTE: planner-tasks-file-behavior new default: 'close ** Docfix *** johnsu01/4-8: Documentation fixes. *** dev/398: planner-el.texi refers to wrong URL *** dev/401: planner-lisp: Add arbitrary functions example * Changes in Planner 3.29 ** New *** dev/369: planner-annotation-symbol-string *** dev/369: planner-create-task-from-note *** dev/370: planner-timewarp *** dev/371: planner-annotation-from-dired *** dev/372: planner-psvn for version control ** Bugfixes *** dev/366: planner-multi read-only prompt, sort-task excursions, planner-appt advice *** dev/367: Always add menu to planner-mode buffers *** dev/368: planner-multi-read-name bugfix from jeho *** dev/369: planner-timeclock-summary-proj bugfix *** dev/370: Group .*? regexp to deal with possible XEmacs bug *** dev/372: planner-vm-browse-url and message IDs *** dev/376: planner-id bugfixes with completed/cancelled tasks *** dev/377: planner-gnus: pick up group name properly *** dev/380: planner-multi replace mapc with mapcar for emacs20 ** Docfixes *** dev/365: Update my sample configuration file *** dev/374: New URL for remind *** dev/375: Carrying over unfinished tasks *** dev/379: Document planner-trunk * Changes in Planner 3.28 ** New *** planner-appt creates appointment reminders from task descriptions and other text. *** planner-trunk helps organize tasks on day and plan pages. Thanks to camalot, dryice, keith. *** Sane completing read for XEmacs planner-multi. *** New option: planner-publish-dates-first-p controls index. ** Bugfix *** Escape planner-multi spaces in annotation names by using emacs-wiki. *** timeclock-summary publishing problem. *** planner-mhe bugfix for using mh-path and utility functions. *** Better Emacs 21 and XEmacs compatibility *** planner-multi and planner-id bugfixes for compatibility with each other. *** planner-replan-task: Preserve initial task location as much as possible. ** Docfix *** Document planner-rank. *** planner-el.texi reorganization along concepts planner-el/README000066400000000000000000000133451226462314700140100ustar00rootroot00000000000000 This is the README file for Planner. Synopsis ======== Planner is an organizer and day planner for Emacs. It helps you keep track of your pending and completed tasks, daily schedule, dates to remember, notes and inspirations. It is a powerful tool not only for managing your time and productivity, but also for keeping within easy keystroke reach all of the information you need to be productive. It can even publish reports charting your work for your personal web page, your conscience, or your soon-to-be-impressed boss. In fact, because it uses as its building blocks simple plain-text files, it is an incredibly modular and flexible tool capable of shaping and handling your personal information in ways whose variety is limited only by your imagination. Because of this, Planner has a very active and generous community who regularly share their innovations with each other. Many of these modules and extensions are included. License ======= Planner 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, or (at your option) any later version. Planner 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 Planner; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Directory contents ================== The directory structure is as follows. top level :: Planner source code and the documentation (planner-el.texi). contrib :: Files that are not a part of Planner proper, but are useful enough to be bundled with Planner. scripts :: Scripts that are used when compiling Planner. Getting started =============== Compilation ----------- This is an optional step, since Emacs Lisp source code does not necessarily have to be byte-compiled. It will yield a speed increase, though. A working copy of Emacs or XEmacs is needed in order to compile Planner. By default, the program that is installed with the name `emacs' will be used. You will also need to have Emacs Muse 3.03 or later installed. See http://emacswiki.org/cgi-bin/wiki/PlannerModeQuickStart for current information on which release of Muse to get, If Muse is not present in the `~/elisp/muse' directory on your system, you will have to change the line that mentions Muse in `scripts/planner-build.el' to something like the following, replacing PATH with the path to Muse. (add-to-list 'load-path "PATH/lisp") If you want to use the `xemacs' binary to perform the compilation, you must copy `Makefile.defs.default' to `Makefile.defs' in the top-level directory, and then edit `Makefile.defs' as follows. You can put either a full path to an Emacs or XEmacs binary or just the command name, as long as it is in the PATH. Depending on your setup, changes to the PREFIX, ELISPDIR, and/or INFODIR variables may also need to be made. EMACS = xemacs SITEFLAG = -no-site-file # Edit the section as necessary install_info = install-info --section "XEmacs 21.4" $(1).info \ $(INFODIR)/dir || : In order for Planner to be byte-compiled properly, you will need to specify the paths to Muse and other external software programs in `scripts/planner-build.el'. If a file fails to be byte-compiled, only its source will be installed. Running `make' should compile the Planner source files in the `lisp' directory. Installation ------------ Planner may be installed into your file hierarchy by doing the following. Copy `Makefile.defs.default' to `Makefile.defs' in the top-level directory, if you haven't done so already. Then edit the `Makefile.defs' file so that ELISPDIR points to where you want the source and compiled Muse files to be installed and INFODIR indicates where to put the Muse manual. As mentioned earlier, you will want to edit EMACS and SITEFLAG as shown in the Compilation section if you are using XEmacs. If you are installing Planner on a Debian system, you might want to change the value of INSTALLINFO as specified in `Makefile.defs'. If you wish to install Planner to different locations than the defaults specify, edit `Makefile.defs' accordingly. Run `make' as a normal user. Run `make install' as the root user if you have chosen installation locations that require this. Insinuation ----------- Two things need to happen in order for Planner to be usable with your version of Emacs or XEmacs. 1. The location of the Planner directory needs to be added to the load path so that your variant of Emacs can find it. 2. You need to load whichever Planner files you wish to make use of. A quick example that accomplishes both of these follows. ;; Add this to your .emacs or .xemacs/init.el file. (add-to-list 'load-path "/path/to/planner") (require 'planner) Documentation ------------- The Planner manual may be generated by running `make doc'. It will produce two files: an Info file called `planner-el.info' and an HTML document called `planner-el.html'. This manual is also available online in several forms at http://www.wjsullivan.net/static/doc/planner/. Further Documentation ===================== The maintainer of Planner has a webpage for it at http://www.wjsullivan.net/PlannerMode.html. Bugs may be reported using the Planner Bug-Tracker at https://gna.org/bugs/?group=planner-el. Planner has a collaborative wiki at http://emacswiki.org/cgi-bin/wiki/PlannerMode. Mailing lists for Planner and some related software exists; consult https://gna.org/mail/?group=planner-el for details on joining them or viewing their contents. planner-el/contrib/000077500000000000000000000000001226462314700145625ustar00rootroot00000000000000planner-el/contrib/schedule.el000066400000000000000000000523571226462314700167140ustar00rootroot00000000000000;;; schedule.el --- calculate schedule completion time ;; Copyright (C) 1999, 2000, 2008 John Wiegley. ;; Author: John Wiegley ;; Created: 20 Jan 1999 ;; Version: 2.0 ;; Keywords: calendar ;; X-URL: http://www.newartisans.com/johnw/Emacs/schedule.el ;; This version of schedule.el is part of Planner. It is not part of ;; GNU Emacs. ;; Planner 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 2, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file provides a single Lisp function: ;; `schedule-completion-time'. It takes an Emacs time object and a ;; quantity of seconds. It returns an Emacs time object that ;; represents when the given number of seconds will be completed, ;; assuming that work can only be done during work hours. ;; ;; The available work hours are affected by several factors: ;; ;; 1. If timeclock.el is being used, the amount of time left ;; in the current workday (timeclock-workday-remaining) ;; 2. The amount of time in each workday (schedule-workday) ;; 3. The definition of a work week (schedule-week) ;; 4. Any holidays defined in the Emacs calendar ;; 5. Any appointments in the Emacs diary ;; ;; Taking all of the "block out" periods into account, ;; `schedule-completion-time' will compute when the given number of ;; seconds will be done, based on your current definitions of time ;; available. ;; ;; As an example, here's a function which, given a list of durations ;; in seconds, will return a list of completion times starting from ;; the current moment: ;; ;; (defun compute-completion-times (&rest durations) ;; "Compute completion times for a list of DURATIONS (in seconds)." ;; (let ((now (current-time))) ;; (mapcar ;; (function ;; (lambda (dura) ;; (setq now (schedule-completion-time now dura)))) ;; durations))) ;; ;; To call this function: ;; ;; (compute-completion-times 3600 7200 3600) ;;; Code: (require 'calendar) (require 'diary-lib) (require 'holidays) (defconst schedule-version "2.0" "This version of schedule.") (defgroup schedule nil "A mode to help keep track of project schedules." :group 'tasks) ;;; User Variables: (defvar schedule-week-length nil "The length of the week in seconds. This variable is computed whenever `schedule-week' is set.") (defcustom schedule-workday (if (boundp 'timeclock-workday) timeclock-workday (* 8 60 60)) "*The length of a work period. If the `timeclock' package is being used, it will be consulted in order to determine a proper default value." :type 'integer :group 'schedule) (defun schedule-duration-to-seconds (code) "Convert the given CODE into a integer quantity of seconds." (if (string-match "\\([0-9.]+\\)\\([smhdw]\\)" code) (let ((amount (string-to-number (match-string 1 code))) (kind (match-string 2 code))) (cond ((equal kind "s") amount) ((equal kind "m") (* amount 60)) ((equal kind "h") (* amount 3600)) ((equal kind "d") (* amount schedule-workday)) ((equal kind "w") (* amount schedule-week-length)) (t (error "Invalid duration code")))) (error "Invalid duration code"))) (defvar schedule-computed-week nil "The meaning of `schedule-week', converted into numeric form.") (defun schedule-calculate-week () "Convert `schedule-week' into `schedule-computed-week'." (setq schedule-week-length 0 schedule-computed-week (mapcar (function (lambda (day) (when day (let ((start (car day))) (if (functionp start) (setq start (funcall start))) (if (string-match "^\\([0-9]+\\):\\([0-9]+\\)\\([ap]\\)m?$" start) (let ((hour (string-to-number (match-string 1 start))) (min (string-to-number (match-string 2 start))) (ampm (match-string 3 start))) (if (and (= hour 12) (string= ampm "a")) (setq hour 0)) (if (and (< hour 12) (string= ampm "p")) (setq hour (+ hour 12))) (let ((length (if (functionp (cadr day)) (funcall (cadr day)) (schedule-duration-to-seconds (cadr day))))) (setq schedule-week-length (+ schedule-week-length length)) (list hour min length))) nil))))) (symbol-value 'schedule-week)))) ; to quiet byte compiler (defcustom schedule-week '(nil ("9:00a" "8h") ("9:00a" "8h") ("9:00a" "8h") ("9:00a" "8h") ("9:00a" "8h") nil) "*A description of what your regular week looks like. The list should be seven elements long, the first entry being for Sunday. Each entry is either nil, or a list of the form (TIME-IN DURATION). TIME-IN should be a string of the form \"11:30a\", or a function returning such a string; DURATION should be a duration string, such as \"8h\", or a function returning a quantity of seconds." :set (lambda (symbol value) (setq schedule-week value) (schedule-calculate-week) schedule-week) :type '(repeat (choice (const :tag "No work" nil) (list :tag "Workday" (choice (string :tag "Time in") function) (choice (string :tag "Duration") function)))) :group 'schedule) (defcustom schedule-diary-period nil "*How many days at a time we should look through the diary. If you have lots of repeating appointments, things may go faster if you decrease this number. If this variable is set to nil, the diary won't be consulted." :set (lambda (symbol value) (if value (require 'diary-lib)) (setq schedule-diary-period value)) :type '(choice (integer :tag "Quantum of days to examine") (const :tag "Don't consult diary" nil)) :group 'schedule) ;;; Internal Variables: (defvar schedule-day-remainder nil "The number of seconds remaining today. Used in calculations only.") (defvar schedule-diary-entries nil "A list of diary entries in a period.") (defvar schedule-diary-entries-begin nil "The time of the beginning of `schedule-diary-entries'.") (defvar schedule-holiday-list nil "A list of dates on which holidays will fall.") (defvar schedule-initialized nil "Non-nil if the scheduling code has been initialized.") ;;; User Functions: ;;;###autoload (defun schedule-completion-time (then count) "Advance THEN by COUNT seconds, skipping the weekends and holidays. THEN must not already be in a holiday or non-worktime. Make sure that `schedule-align-now' is called at least once before this function ever gets called." (unless schedule-initialized (schedule-initialize)) ;; determine how much time is left in the current day (if (and (featurep 'timeclock) (timeclock-currently-in-p) (> (timeclock-workday-remaining) 0)) (setq schedule-day-remainder (timeclock-workday-remaining)) (setq then (schedule-align-now then) schedule-day-remainder (cdr (schedule-nearest-workday then)))) ;; now calculate when the timeframe will actually end (while (> count 0) (if (< count schedule-day-remainder) (setq then (schedule-time-add-seconds then count) schedule-day-remainder (- schedule-day-remainder count) count 0) (setq count (- count schedule-day-remainder) then (schedule-align-now (schedule-advance-day then)) schedule-day-remainder (cdr (schedule-nearest-workday then))))) then) ;;; Internal Functions: (defun schedule-initialize () "Initialize the scheduling computation code." ;; initialize the cached diary entry lists (setq schedule-diary-entries nil schedule-diary-entries-begin nil) ;; if someone changes these values outside the customize buffer, ;; they will have to reload this module. (unless schedule-computed-week (schedule-calculate-week)) ;; determine the holidays that will apply (setq schedule-holiday-list nil) (let ((h calendar-holidays)) (while h (if (eq (caar h) 'holiday-fixed) (setq schedule-holiday-list (cons (list (nth 1 (car h)) (nth 2 (car h))) schedule-holiday-list))) (setq h (cdr h)))) (setq schedule-initialized t)) (defsubst schedule-time-add-seconds (time seconds) "To TIME, add SECONDS. Return result as a time value." (let* ((secint (truncate seconds)) (hi (/ secint 65536)) (lo (% secint 65536)) (calc (+ (cadr time) lo))) (if (< calc 65536) (list (+ (car time) hi) calc) (list (+ (car time) (1+ hi)) (% calc 65536))))) (defsubst schedule-advance-day (then &optional count) "Given a time THEN, advance it by COUNT days." (schedule-time-add-seconds then (* 86400 (or count 1)))) (defsubst schedule-time-to-seconds (time) "Convert TIME to a floating point number." (+ (* (car time) 65536.0) (cadr time) (/ (or (car (cdr (cdr time))) 0) 1000000.0))) (defsubst schedule-seconds-to-time (seconds) "Convert SECONDS (a floating point number) to an Emacs time structure." (list (floor seconds 65536) (floor (mod seconds 65536)) (floor (* (- seconds (ffloor seconds)) 1000000)))) (defsubst schedule-time-diff (t1 t2) "Return the difference in seconds between T1 and T2." (- (schedule-time-to-seconds t1) (schedule-time-to-seconds t2))) (defsubst schedule-time-less-p (t1 t2) "Say whether time T1 is less than time T2." (or (< (car t1) (car t2)) (and (= (car t1) (car t2)) (< (nth 1 t1) (nth 1 t2))))) (defsubst schedule-time-date (then) "Return the DATE part of THEN, in calendar friendly format." (let* ((elems (decode-time then))) (list (nth 4 elems) (nth 3 elems) (nth 5 elems)))) (defun schedule-seconds-to-duration (seconds) "Convert SECONDS to a compact time string." (let ((string (cond ((< seconds 60) (format "%ds" seconds)) ((< seconds 3600) (format "%.1fm" (/ (float seconds) 60.0))) ((< seconds schedule-workday) (format "%.1fh" (/ (float seconds) 3600.0))) ((< seconds schedule-week-length) (format "%.1fd" (/ (float seconds) schedule-workday))) (t (format "%.1fw" (/ (float seconds) schedule-week-length)))))) (if (string-match "\\.0\\([mhdw]\\)" string) (replace-match "\\1" t nil string) string))) (defun schedule-day-begin (then) "Given a time THEN, return its beginning time and length. `schedule-week' is consulted to determine what the typical begin time and length are for a given day of the week. The return value is a cons cell, with the car being a time value, and the cdr the number of seconds during that day." (let* ((elems (decode-time then)) (dow (nth 6 elems)) (today (nth dow schedule-computed-week))) (if (not today) (cons then 0) (cons (apply 'encode-time 0 (cadr today) (car today) (nthcdr 3 elems)) (nth 2 today))))) ;; This is from "cal-desk-calendar.el". It should be part of Emacs. (defun schedule-diary-entry-times (s) "List of times at beginning of string S in military-style integers. For example, returns 1325 for 1:25pm. Returns -9999 if no time is recognized. The recognized forms are XXXX or X:XX or XX:XX (military time), XXam or XXpm, and XX:XXam or XX:XXpm. If a range is given, the list contains two elements which will be the start and end of the range. If only one time is given, both elements of the list will contain the time given." (cond ;; Hour and minute range XX:XX-XX:XX[ap]m ((string-match "^[ ]*\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)-\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\>" s) (list (+ (* 100 (% (string-to-int (substring s (match-beginning 1) (match-end 1))) 12)) (string-to-int (substring s (match-beginning 2) (match-end 2))) (if (string-equal "a" (substring s (match-beginning 5) (match-end 5))) 0 1200)) (+ (* 100 (% (string-to-int (substring s (match-beginning 3) (match-end 3))) 12)) (string-to-int (substring s (match-beginning 4) (match-end 4))) (if (string-equal "a" (substring s (match-beginning 5) (match-end 5))) 0 1200)) (substring s (+ 2 (match-end 5))))) ;; Military time range ((string-match "^[ ]*\\([0-9]?[0-9]\\):?\\([0-9][0-9]\\)-\\([0-9]?[0-9]\\):?\\([0-9][0-9]\\)\\(\\|[^ap]\\)" s) (list (+ (* 100 (string-to-int (substring s (match-beginning 1) (match-end 1)))) (string-to-int (substring s (match-beginning 2) (match-end 2)))) (+ (* 100 (string-to-int (substring s (match-beginning 3) (match-end 3)))) (string-to-int (substring s (match-beginning 4) (match-end 4)))) (substring s (1+ (match-end 4))))) ;; Hour range HH[ap]m-HH[ap]m ((string-match "^[ ]*\\([0-9]?[0-9]\\)\\([ap]\\)m-\\([0-9]?[0-9]\\)\\([ap]\\)m\\>" s) (list (+ (* 100 (% (string-to-int (substring s (match-beginning 1) (match-end 1))) 12)) (if (string-equal "a" (substring s (match-beginning 2) (match-end 2))) 0 1200)) (+ (* 100 (% (string-to-int (substring s (match-beginning 3) (match-end 3))) 12)) (if (string-equal "a" (substring s (match-beginning 4) (match-end 4))) 0 1200)) (substring s (+ 2 (match-end 4))))) ;; Hour range HH-HH[ap]m ((string-match "^[ ]*\\([0-9]?[0-9]\\)-\\([0-9]?[0-9]\\)\\([ap]\\)m\\>" s) (list (+ (* 100 (% (string-to-int (substring s (match-beginning 1) (match-end 1))) 12)) (if (string-equal "a" (substring s (match-beginning 3) (match-end 3))) 0 1200)) (+ (* 100 (% (string-to-int (substring s (match-beginning 2) (match-end 2))) 12)) (if (string-equal "a" (substring s (match-beginning 3) (match-end 3))) 0 1200)) (substring s (+ 2 (match-end 3))))) ;; Hour and minute range XX:XX[ap]m-XX:XX[ap]m ((string-match "^[ ]*\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m-\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\>" s) (list (+ (* 100 (% (string-to-int (substring s (match-beginning 1) (match-end 1))) 12)) (string-to-int (substring s (match-beginning 2) (match-end 2))) (if (string-equal "a" (substring s (match-beginning 3) (match-end 3))) 0 1200)) (+ (* 100 (% (string-to-int (substring s (match-beginning 4) (match-end 4))) 12)) (string-to-int (substring s (match-beginning 5) (match-end 5))) (if (string-equal "a" (substring s (match-beginning 6) (match-end 6))) 0 1200)) (substring s (+ 2 (match-end 6))))) ;; Military time ((string-match "^[ ]*\\([0-9]?[0-9]\\):?\\([0-9][0-9]\\)\\(\\>\\|[^ap]\\)" s) (let ((time (+ (* 100 (string-to-int (substring s (match-beginning 1) (match-end 1)))) (string-to-int (substring s (match-beginning 2) (match-end 2)))))) (list time time (substring s (1+ (match-end 2)))))) ;; Hour only XXam or XXpm ((string-match "^[ ]*\\([0-9]?[0-9]\\)\\([ap]\\)m\\>" s) (let ((time (+ (* 100 (% (string-to-int (substring s (match-beginning 1) (match-end 1))) 12)) (if (string-equal "a" (substring s (match-beginning 2) (match-end 2))) 0 1200)))) (list time time (substring s (+ 2 (match-end 2)))))) ;; Hour and minute XX:XXam or XX:XXpm ((string-match "^[ ]*\\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\>" s) (let ((time (+ (* 100 (% (string-to-int (substring s (match-beginning 1) (match-end 1))) 12)) (string-to-int (substring s (match-beginning 2) (match-end 2))) (if (string-equal "a" (substring s (match-beginning 3) (match-end 3))) 0 1200)))) (list time time (substring s (+ 2 (match-end 3)))))) ;; Sunrise/sunset produced by %%(diary-sunrise-sunset) ((string-match "^[ ]*Sunrise \\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\> ([A-Za-z0-9+-]*), sunset \\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\> ([A-Za-z0-9+-]*)\\(.*\\)" s) (let ((sunrise-time (+ (* 100 (% (string-to-int (substring s (match-beginning 1) (match-end 1))) 12)) (string-to-int (substring s (match-beginning 2) (match-end 2))) (if (string-equal "a" (substring s (match-beginning 3) (match-end 3))) 0 1200))) (sunset-time (+ (* 100 (% (string-to-int (substring s (match-beginning 4) (match-end 4))) 12)) (string-to-int (substring s (match-beginning 5) (match-end 5))) (if (string-equal "a" (substring s (match-beginning 6) (match-end 6))) 0 1200)))) (list sunrise-time sunrise-time (concat "Sunrise " (substring s (match-beginning 1) (match-end 2)) "am" (substring s (1+ (match-end 6))) (substring s (match-beginning 7) (match-end 7))) sunset-time sunset-time (concat "Sunset " (substring s (match-beginning 4) (match-end 5)) "pm" (substring s (1+ (match-end 6))) (substring s (match-beginning 7) (match-end 7)))))) ;; Lunar phase produced by %%(diary-phases-of-moon) ((string-match "^[ ]*\\(New\\|First Quarter\\|Full\\|Last Quarter\\) Moon \\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\> ([A-Z0-9+-]*)" s) (let ((time (+ (* 100 (% (string-to-int (substring s (match-beginning 2) (match-end 2))) 12)) (string-to-int (substring s (match-beginning 3) (match-end 3))) (if (string-equal "a" (substring s (match-beginning 4) (match-end 4))) 0 1200)))) (list time time s))) ;; Equinox/Solstice produced by %%(diary-equinoxes-solstices) ((string-match "^[ ]*\\(Vernal Equinox\\|Summer Solstice\\|Autumnal Equinox\\|Winter Solstice\\) \\([0-9]?[0-9]\\):\\([0-9][0-9]\\)\\([ap]\\)m\\> ([A-Z0-9+-]*)" s) (let ((time (+ (* 100 (% (string-to-int (substring s (match-beginning 2) (match-end 2))) 12)) (string-to-int (substring s (match-beginning 3) (match-end 3))) (if (string-equal "a" (substring s (match-beginning 4) (match-end 4))) 0 1200)))) (list time time s))) ;; Unrecognizable (t (list -9999 -9999 s)))) (defun schedule-convert-diary-time (date diary-time) "Convert the given DATE and DIARY-TIME into a time value. DIARY-TIME is an integer of the form HHMM, as returned by `schedule-diary-entry-times'." (let ((minutes (* (+ (* (/ diary-time 100) 60) (% diary-time 100)) 60))) (encode-time 0 (% minutes 60) (truncate (/ minutes 60)) (cadr date) (car date) (nth 2 date) nil))) (defun schedule-get-diary-entries (then) "Find if there are any diary entries occurring THEN (a time value). Return the amount of time they are scheduled to consume." (let ((then-date (schedule-time-date then)) (day-length (schedule-day-begin then)) (diff (and schedule-diary-entries-begin (truncate (/ (schedule-time-diff then schedule-diary-entries-begin) 86400))))) (if (or (not schedule-diary-entries) (> diff schedule-diary-period)) (let ((display-hook diary-display-hook)) (unwind-protect (save-window-excursion (setq diary-display-hook nil schedule-diary-entries (list-diary-entries then-date schedule-diary-period) schedule-diary-entries-begin then)) (setq diary-display-hook display-hook)))) (let ((entry schedule-diary-entries) (length 0)) (while entry (let ((date (caar entry))) (if (equal date then-date) (let* ((times (schedule-diary-entry-times (cadr (car entry)))) (first (schedule-convert-diary-time (cadr (car entry)) (car times))) (last (schedule-convert-diary-time (cadr (car entry)) (cadr times)))) (if (and (schedule-time-less-p (car day-length) first) (schedule-time-less-p last (schedule-time-add-seconds (car day-length) (cdr day-length)))) (setq length (+ length (- (schedule-time-diff last first)))))))) (setq entry (cdr entry))) length))) (defun schedule-nearest-workday (then) "Given a time THEN, find the nearest workday." (let ((max 8) entry) (while (and (> max 0) (setq entry (schedule-day-begin then)) (or (not entry) (= (cdr entry) 0))) (setq then (schedule-advance-day then) max (1- max))) (if (= max 0) (error "There are is no work time defined during the week")) (and schedule-diary-period (setcdr entry (- (cdr entry) (schedule-get-diary-entries then)))) entry)) (defun schedule-nearest-true-workday (then) "Given a time THEN, find the nearest real workday (not a holiday)." (let ((max 365) entry) (while (and (> max 0) (setq entry (schedule-nearest-workday then)) ;; jww (1999-04-23): this will need to be updated to ;; handle floating holidays (let* ((date (schedule-time-date (car entry))) (mon-day (list (car date) (cadr date)))) (member mon-day schedule-holiday-list))) (setq then (car entry) then (schedule-advance-day then) max (1- max))) (if (= max 0) (error "There is no time available for at least a year")) entry)) (defun schedule-align-now (then) "Given a time THEN, move it ahead to the next valid moment." (let ((day (schedule-nearest-true-workday then))) (if (schedule-time-less-p then (car day)) (car day) (if (> (- (schedule-time-diff then (car day))) (cdr day)) (car (schedule-nearest-true-workday (schedule-advance-day then))) then)))) (provide 'schedule) ;;; schedule.el ends here planner-el/contrib/timeclock.el000066400000000000000000001447141226462314700170710ustar00rootroot00000000000000;;; timeclock.el --- mode for keeping track of how much you work ;; Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2006, 2008 Adrian Aichner ;; Author: John Wiegley ;; Created: 25 Mar 1999 ;; Version: 2.7 ;; Keywords: calendar data ;; This version of timeclock.el is part of Planner. It is not part of ;; GNU Emacs. ;; Planner 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 2, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This mode is for keeping track of time intervals. You can use it ;; for whatever purpose you like, but the typical scenario is to keep ;; track of how much time you spend working on certain projects. ;; ;; Use `timeclock-in' when you start on a project, and `timeclock-out' ;; when you're done. Once you've collected some data, you can use ;; `timeclock-workday-remaining' to see how much time is left to be ;; worked today (where `timeclock-workday' specifies the length of the ;; working day), and `timeclock-when-to-leave' to calculate when you're free. ;; You'll probably want to bind the timeclock commands to some handy ;; keystrokes. At the moment, C-x t is unused: ;; ;; (require 'timeclock) ;; ;; (define-key ctl-x-map "ti" 'timeclock-in) ;; (define-key ctl-x-map "to" 'timeclock-out) ;; (define-key ctl-x-map "tc" 'timeclock-change) ;; (define-key ctl-x-map "tr" 'timeclock-reread-log) ;; (define-key ctl-x-map "tu" 'timeclock-update-modeline) ;; (define-key ctl-x-map "tw" 'timeclock-when-to-leave-string) ;; If you want Emacs to display the amount of time "left" to your ;; workday in the modeline, you can either set the value of ;; `timeclock-modeline-display' to t using M-x customize, or you ;; can add this code to your .emacs file: ;; ;; (require 'timeclock) ;; (timeclock-modeline-display) ;; ;; To cancel this modeline display at any time, just call ;; `timeclock-modeline-display' again. ;; You may also want Emacs to ask you before exiting, if you are ;; currently working on a project. This can be done either by setting ;; `timeclock-ask-before-exiting' to t using M-x customize (this is ;; the default), or by adding the following to your .emacs file: ;; ;; (add-hook 'kill-emacs-query-functions 'timeclock-query-out) ;; NOTE: If you change your .timelog file without using timeclock's ;; functions, or if you change the value of any of timeclock's ;; customizable variables, you should run the command ;; `timeclock-reread-log'. This will recompute any discrepancies in ;; your average working time, and will make sure that the various ;; display functions return the correct value. ;;; History: ;; Version 2.7: ;; ;; Include changes made on 2006-08-01 by Adrian Aichner ;; which make it easier to work with a ;; pgp-encrypted timeclock file. ;;; Code: (unless (featurep 'xemacs) (when (fboundp 'planner-display-warning) (planner-display-warning (concat "Do not use this version of timeclock.el with Emacs.\n" "\nYour version of Emacs almost certainly comes with a" " version of\ntimeclock.el already, so please use that" " instead. One way to solve\nthis is to use the" " following.\n" "\n (add-to-list 'load-path \"path/to/planner/contrib\"" " t)\n\nThe `t' argument will put this at the bottom of" " the load path."))) (error "Do not use this version of timeclock.el with Emacs")) (defgroup timeclock nil "Keeping track of the time that gets spent." :group 'data) ;;; User Variables: (defcustom timeclock-file (convert-standard-filename "~/.timelog") "*The file used to store timeclock data in." :type 'file :group 'timeclock) (defcustom timeclock-workday (* 8 60 60) "*The length of a work period." :type 'integer :group 'timeclock) (defcustom timeclock-relative t "*Whether to maken reported time relative to `timeclock-workday'. For example, if the length of a normal workday is eight hours, and you work four hours on Monday, then the amount of time \"remaining\" on Tuesday is twelve hours -- relative to an averaged work period of eight hours -- or eight hours, non-relative. So relative time takes into account any discrepancy of time under-worked or over-worked on previous days. This only affects the timeclock modeline display." :type 'boolean :group 'timeclock) (defcustom timeclock-get-project-function 'timeclock-ask-for-project "*The function used to determine the name of the current project. When clocking in, and no project is specified, this function will be called to determine what is the current project to be worked on. If this variable is nil, no questions will be asked." :type 'function :group 'timeclock) (defcustom timeclock-get-reason-function 'timeclock-ask-for-reason "*A function used to determine the reason for clocking out. When clocking out, and no reason is specified, this function will be called to determine what is the reason. If this variable is nil, no questions will be asked." :type 'function :group 'timeclock) (defcustom timeclock-get-workday-function nil "*A function used to determine the length of today's workday. The first time that a user clocks in each day, this function will be called to determine what is the length of the current workday. If the return value is nil, or equal to `timeclock-workday', nothing special will be done. If it is a quantity different from `timeclock-workday', however, a record will be output to the timelog file to note the fact that that day has a length that is different from the norm." :type '(choice (const nil) function) :group 'timeclock) (defcustom timeclock-ask-before-exiting t "*If non-nil, ask if the user wants to clock out before exiting Emacs. This variable only has effect if set with \\[customize]." :set (lambda (symbol value) (if value (add-hook 'kill-emacs-query-functions 'timeclock-query-out) (remove-hook 'kill-emacs-query-functions 'timeclock-query-out)) (setq timeclock-ask-before-exiting value)) :type 'boolean :group 'timeclock) (defvar timeclock-history '() "History of previously used timeclock values.") (defcustom timeclock-use-history nil "*If non-nil, user is prompted for timestamp, previous values are available via history mechanism. \\{minibuffer-local-map}. This variable only has effect if set with \\[customize]." :type 'boolean :group 'timeclock) (defvar timeclock-update-timer nil "The timer used to update `timeclock-mode-string'.") ;; For byte-compiler. (defvar display-time-hook) (defvar timeclock-modeline-display) (defcustom timeclock-use-display-time t "*If non-nil, use `display-time-hook' for doing modeline updates. The advantage of this is that one less timer has to be set running amok in Emacs' process space. The disadvantage is that it requires you to have `display-time' running. If you don't want to use `display-time', but still want the modeline to show how much time is left, set this variable to nil. Changing the value of this variable while timeclock information is being displayed in the modeline has no effect. You should call the function `timeclock-modeline-display' with a positive argument to force an update." :set (lambda (symbol value) (let ((currently-displaying (and (boundp 'timeclock-modeline-display) timeclock-modeline-display))) ;; if we're changing to the state that ;; `timeclock-modeline-display' is already using, don't ;; bother toggling it. This happens on the initial loading ;; of timeclock.el. (if (and currently-displaying (or (and value (boundp 'display-time-hook) (memq 'timeclock-update-modeline display-time-hook)) (and (not value) timeclock-update-timer))) (setq currently-displaying nil)) (and currently-displaying (set-variable 'timeclock-modeline-display nil)) (setq timeclock-use-display-time value) (and currently-displaying (set-variable 'timeclock-modeline-display t)) timeclock-use-display-time)) :type 'boolean :group 'timeclock :require 'time) (defcustom timeclock-first-in-hook nil "*A hook run for the first \"in\" event each day. Note that this hook is run before recording any events. Thus the value of `timeclock-hours-today', `timeclock-last-event' and the return value of function `timeclock-last-period' are relative previous to today." :type 'hook :group 'timeclock) (defcustom timeclock-load-hook nil "*Hook that gets run after timeclock has been loaded." :type 'hook :group 'timeclock) (defcustom timeclock-in-hook nil "*A hook run every time an \"in\" event is recorded." :type 'hook :group 'timeclock) (defcustom timeclock-day-over-hook nil "*A hook that is run when the workday has been completed. This hook is only run if the current time remaining is being displayed in the modeline. See the variable `timeclock-modeline-display'." :type 'hook :group 'timeclock) (defcustom timeclock-out-hook nil "*A hook run every time an \"out\" event is recorded." :type 'hook :group 'timeclock) (defcustom timeclock-done-hook nil "*A hook run every time a project is marked as completed." :type 'hook :group 'timeclock) (defcustom timeclock-event-hook nil "*A hook run every time any event is recorded." :type 'hook :group 'timeclock) (defvar timeclock-last-event nil "A list containing the last event that was recorded. The format of this list is (CODE TIME PROJECT).") (defvar timeclock-last-event-workday nil "The number of seconds in the workday of `timeclock-last-event'.") ;;; Internal Variables: (defvar timeclock-discrepancy nil "A variable containing the time discrepancy before the last event. Normally, timeclock assumes that you intend to work for `timeclock-workday' seconds every day. Any days in which you work more or less than this amount is considered either a positive or a negative discrepancy. If you work in such a manner that the discrepancy is always brought back to zero, then you will by definition have worked an average amount equal to `timeclock-workday' each day.") (defvar timeclock-elapsed nil "A variable containing the time elapsed for complete periods today. This value is not accurate enough to be useful by itself. Rather, call `timeclock-workday-elapsed', to determine how much time has been worked so far today. Also, if `timeclock-relative' is nil, this value will be the same as `timeclock-discrepancy'.") ; ? gm (defvar timeclock-last-period nil "Integer representing the number of seconds in the last period. Note that you shouldn't access this value, but instead should use the function `timeclock-last-period'.") (defvar timeclock-mode-string nil "The timeclock string (optionally) displayed in the modeline. The time is bracketed by <> if you are clocked in, otherwise by [].") (defvar timeclock-day-over nil "The date of the last day when notified \"day over\" for.") ;;; User Functions: ;;;###autoload (defun timeclock-modeline-display (&optional arg) "Toggle display of the amount of time left today in the modeline. If `timeclock-use-display-time' is non-nil (the default), then the function `display-time-mode' must be active, and the modeline will be updated whenever the time display is updated. Otherwise, the timeclock will use its own sixty second timer to do its updating. With prefix ARG, turn modeline display on if and only if ARG is positive. Returns the new status of timeclock modeline display (non-nil means on)." (interactive "P") ;; cf display-time-mode. (setq timeclock-mode-string "") (or global-mode-string (setq global-mode-string '(""))) (let ((on-p (if arg (> (prefix-numeric-value arg) 0) (not timeclock-modeline-display)))) (if on-p (progn (or (memq 'timeclock-mode-string global-mode-string) (setq global-mode-string (append global-mode-string '(timeclock-mode-string)))) (unless (memq 'timeclock-update-modeline timeclock-event-hook) (add-hook 'timeclock-event-hook 'timeclock-update-modeline)) (when timeclock-update-timer (timeclock-cancel-timer timeclock-update-timer) (setq timeclock-update-timer nil)) (if (boundp 'display-time-hook) (remove-hook 'display-time-hook 'timeclock-update-modeline)) (if timeclock-use-display-time (progn ;; Update immediately so there is a visible change ;; on calling this function. (if display-time-mode (timeclock-update-modeline) (message "Activate `display-time-mode' to see \ timeclock information")) (add-hook 'display-time-hook 'timeclock-update-modeline)) (setq timeclock-update-timer (run-at-time nil 60 'timeclock-update-modeline)))) (setq global-mode-string (delq 'timeclock-mode-string global-mode-string)) (remove-hook 'timeclock-event-hook 'timeclock-update-modeline) (if (boundp 'display-time-hook) (remove-hook 'display-time-hook 'timeclock-update-modeline)) (when timeclock-update-timer (timeclock-cancel-timer timeclock-update-timer) (setq timeclock-update-timer nil))) (force-mode-line-update) (setq timeclock-modeline-display on-p))) ;; This has to be here so that the function definition of ;; `timeclock-modeline-display' is known to the "set" function. (defcustom timeclock-modeline-display nil "Toggle modeline display of time remaining. You must modify via \\[customize] for this variable to have an effect." :set (lambda (symbol value) (setq timeclock-modeline-display (timeclock-modeline-display (or value 0)))) :type 'boolean :group 'timeclock :require 'timeclock) (defsubst timeclock-time-to-date (time) "Convert the TIME value to a textual date string." (format-time-string "%Y/%m/%d" time)) ;;;###autoload (defun timeclock-in (&optional arg project find-project) "Clock in, recording the current time moment in the timelog. With a numeric prefix ARG, record the fact that today has only that many hours in it to be worked. If arg is a non-numeric prefix arg \(non-nil, but not a number), 0 is assumed (working on a holiday or weekend). *If not called interactively, ARG should be the number of _seconds_ worked today*. This feature only has effect the first time this function is called within a day. PROJECT is the project being clocked into. If PROJECT is nil, and FIND-PROJECT is non-nil -- or the user calls `timeclock-in' interactively -- call the function `timeclock-get-project-function' to discover the name of the project." (interactive (list (and current-prefix-arg (if (numberp current-prefix-arg) (* current-prefix-arg 60 60) 0)))) (if (equal (car timeclock-last-event) "i") (error "You've already clocked in!") (unless timeclock-last-event (timeclock-reread-log)) ;; Either no log file, or day has rolled over. (unless (and timeclock-last-event (equal (timeclock-time-to-date (cadr timeclock-last-event)) (timeclock-time-to-date (current-time)))) (let ((workday (or (and (numberp arg) arg) (and arg 0) (and timeclock-get-workday-function (funcall timeclock-get-workday-function)) timeclock-workday))) (run-hooks 'timeclock-first-in-hook) ;; settle the discrepancy for the new day (setq timeclock-discrepancy (- (or timeclock-discrepancy 0) workday)) (if (not (= workday timeclock-workday)) (timeclock-log "h" (and (numberp arg) (number-to-string arg)))))) (timeclock-log "i" (or project (and timeclock-get-project-function (or find-project (interactive-p)) (funcall timeclock-get-project-function)))) (run-hooks 'timeclock-in-hook))) ;;;###autoload (defun timeclock-out (&optional arg reason find-reason) "Clock out, recording the current time moment in the timelog. If a prefix ARG is given, the user has completed the project that was begun during the last time segment. REASON is the user's reason for clocking out. If REASON is nil, and FIND-REASON is non-nil -- or the user calls `timeclock-out' interactively -- call the function `timeclock-get-reason-function' to discover the reason." (interactive "P") (or timeclock-last-event (error "You haven't clocked in!")) (if (equal (downcase (car timeclock-last-event)) "o") (error "You've already clocked out!") (timeclock-log (if arg "O" "o") (or reason (and timeclock-get-reason-function (or find-reason (interactive-p)) (funcall timeclock-get-reason-function)))) (run-hooks 'timeclock-out-hook) (if arg (run-hooks 'timeclock-done-hook)))) ;; Should today-only be removed in favour of timeclock-relative? - gm (defsubst timeclock-workday-remaining (&optional today-only) "Return the number of seconds until the workday is complete. The amount returned is relative to the value of `timeclock-workday'. If TODAY-ONLY is non-nil, the value returned will be relative only to the time worked today, and not to past time." (let ((discrep (timeclock-find-discrep))) (if discrep (- (if today-only (cadr discrep) (car discrep))) 0.0))) ;;;###autoload (defun timeclock-status-string (&optional show-seconds today-only) "Report the overall timeclock status at the present moment. If SHOW-SECONDS is non-nil, display second resolution. If TODAY-ONLY is non-nil, the display will be relative only to time worked today, ignoring the time worked on previous days." (interactive "P") (let ((remainder (timeclock-workday-remaining)) ; today-only? (last-in (equal (car timeclock-last-event) "i")) status) (setq status (format "Currently %s since %s (%s), %s %s, leave at %s" (if last-in "IN" "OUT") (if show-seconds (format-time-string "%-I:%M:%S %p" (nth 1 timeclock-last-event)) (format-time-string "%-I:%M %p" (nth 1 timeclock-last-event))) (or (nth 2 timeclock-last-event) (if last-in "**UNKNOWN**" "workday over")) (timeclock-seconds-to-string remainder show-seconds t) (if (> remainder 0) "remaining" "over") (timeclock-when-to-leave-string show-seconds today-only))) (if (interactive-p) (message status) status))) ;;;###autoload (defun timeclock-change (&optional arg project) "Change to working on a different project. This clocks out of the current project, then clocks in on a new one. With a prefix ARG, consider the previous project as finished at the time of changeover. PROJECT is the name of the last project you were working on." (interactive "P") (timeclock-out arg) (timeclock-in nil project (interactive-p))) ;;;###autoload (defun timeclock-query-out () "Ask the user whether to clock out. This is a useful function for adding to `kill-emacs-query-functions'." (and (equal (car timeclock-last-event) "i") (y-or-n-p "You're currently clocking time, clock out? ") (timeclock-out)) ;; Unconditionally return t for `kill-emacs-query-functions'. t) ;;;###autoload (defun timeclock-reread-log () "Re-read the timeclock, to account for external changes. Returns the new value of `timeclock-discrepancy'." (interactive) (setq timeclock-discrepancy nil) (timeclock-find-discrep) (if (and timeclock-discrepancy timeclock-modeline-display) (timeclock-update-modeline)) timeclock-discrepancy) (defun timeclock-seconds-to-string (seconds &optional show-seconds reverse-leader) "Convert SECONDS into a compact time string. If SHOW-SECONDS is non-nil, make the resolution of the return string include the second count. If REVERSE-LEADER is non-nil, it means to output a \"+\" if the time value is negative, rather than a \"-\". This is used when negative time values have an inverted meaning (such as with time remaining, where negative time really means overtime)." (if show-seconds (format "%s%d:%02d:%02d" (if (< seconds 0) (if reverse-leader "+" "-") "") (truncate (/ (abs seconds) 60 60)) (% (truncate (/ (abs seconds) 60)) 60) (% (truncate (abs seconds)) 60)) (format "%s%d:%02d" (if (< seconds 0) (if reverse-leader "+" "-") "") (truncate (/ (abs seconds) 60 60)) (% (truncate (/ (abs seconds) 60)) 60)))) (defsubst timeclock-currently-in-p () "Return non-nil if the user is currently clocked in." (equal (car timeclock-last-event) "i")) ;;;###autoload (defun timeclock-workday-remaining-string (&optional show-seconds today-only) "Return a string representing the amount of time left today. Display second resolution if SHOW-SECONDS is non-nil. If TODAY-ONLY is non-nil, the display will be relative only to time worked today. See `timeclock-relative' for more information about the meaning of \"relative to today\"." (interactive) (let ((string (timeclock-seconds-to-string (timeclock-workday-remaining today-only) show-seconds t))) (if (interactive-p) (message string) string))) (defsubst timeclock-workday-elapsed () "Return the number of seconds worked so far today. If RELATIVE is non-nil, the amount returned will be relative to past time worked. The default is to return only the time that has elapsed so far today." (let ((discrep (timeclock-find-discrep))) (if discrep (nth 2 discrep) 0.0))) ;;;###autoload (defun timeclock-workday-elapsed-string (&optional show-seconds) "Return a string representing the amount of time worked today. Display seconds resolution if SHOW-SECONDS is non-nil. If RELATIVE is non-nil, the amount returned will be relative to past time worked." (interactive) (let ((string (timeclock-seconds-to-string (timeclock-workday-elapsed) show-seconds))) (if (interactive-p) (message string) string))) (defsubst timeclock-time-to-seconds (time) "Convert TIME to a floating point number." (+ (* (car time) 65536.0) (cadr time) (/ (or (car (cdr (cdr time))) 0) 1000000.0))) (defsubst timeclock-seconds-to-time (seconds) "Convert SECONDS (a floating point number) to an Emacs time structure." (list (floor seconds 65536) (floor (mod seconds 65536)) (floor (* (- seconds (ffloor seconds)) 1000000)))) ;; Should today-only be removed in favour of timeclock-relative? - gm (defsubst timeclock-when-to-leave (&optional today-only) "Return a time value representing the end of today's workday. If TODAY-ONLY is non-nil, the value returned will be relative only to the time worked today, and not to past time." (timeclock-seconds-to-time (- (timeclock-time-to-seconds (current-time)) (let ((discrep (timeclock-find-discrep))) (if discrep (if today-only (cadr discrep) (car discrep)) 0.0))))) ;;;###autoload (defun timeclock-when-to-leave-string (&optional show-seconds today-only) "Return a string representing the end of today's workday. This string is relative to the value of `timeclock-workday'. If SHOW-SECONDS is non-nil, the value printed/returned will include seconds. If TODAY-ONLY is non-nil, the value returned will be relative only to the time worked today, and not to past time." ;; Should today-only be removed in favour of timeclock-relative? - gm (interactive) (let* ((then (timeclock-when-to-leave today-only)) (string (if show-seconds (format-time-string "%-I:%M:%S %p" then) (format-time-string "%-I:%M %p" then)))) (if (interactive-p) (message string) string))) ;;; Internal Functions: (defvar timeclock-project-list nil) (defvar timeclock-last-project nil) (defun timeclock-get-timeclock-file-buffer (file) "Return the buffer visiting timeclock-file FILE." (or (get-file-buffer file) (find-file-noselect file))) (defun timeclock-propertize (string &rest props) (let ((string (copy-sequence string))) (while props (put-text-property 0 (length string) (nth 0 props) (nth 1 props) string) (setq props (cddr props))) string)) (defun timeclock-cancel-timer (timer) (cond ((fboundp 'cancel-timer) (cancel-timer timer)) ((fboundp 'delete-itimer) (delete-itimer timer)) (t (error "Cannot find `cancel-timer' variant")))) (defun timeclock-completing-read (prompt alist &optional default) "A version of `completing-read' that works on both Emacs and XEmacs." (if (featurep 'xemacs) (let ((str (completing-read prompt alist))) (if (or (null str) (= (length str) 0)) default str)) (completing-read prompt alist nil nil nil nil default))) (defun timeclock-ask-for-project () "Ask the user for the project they are clocking into." (timeclock-completing-read (format "Clock into which project (default \"%s\"): " (or timeclock-last-project (car timeclock-project-list))) (mapcar 'list timeclock-project-list) (or timeclock-last-project (car timeclock-project-list)))) (defvar timeclock-reason-list nil) (defun timeclock-ask-for-reason () "Ask the user for the reason they are clocking out." (timeclock-completing-read "Reason for clocking out: " (mapcar 'list timeclock-reason-list))) (defun timeclock-update-modeline () "Update the `timeclock-mode-string' displayed in the modeline. The value of `timeclock-relative' affects the display as described in that variable's documentation." (interactive) (let ((remainder (timeclock-workday-remaining (not timeclock-relative))) (last-in (equal (car timeclock-last-event) "i"))) (when (and (< remainder 0) (not (and timeclock-day-over (equal timeclock-day-over (timeclock-time-to-date (current-time)))))) (setq timeclock-day-over (timeclock-time-to-date (current-time))) (run-hooks 'timeclock-day-over-hook)) (setq timeclock-mode-string (timeclock-propertize (format " %c%s%c " (if last-in ?< ?[) (timeclock-seconds-to-string remainder nil t) (if last-in ?> ?])) 'help-echo "timeclock: time remaining")))) (put 'timeclock-mode-string 'risky-local-variable t) (defun timeclock-log (code &optional project) "Log the event CODE to the timeclock log, at the time of call. If PROJECT is a string, it represents the project which the event is being logged for. Normally only \"in\" events specify a project." (with-current-buffer (timeclock-get-timeclock-file-buffer timeclock-file) (goto-char (point-max)) (if (not (bolp)) (insert "\n")) (let ((now (current-time))) (insert code " " (if timeclock-use-history (read-string "timeclock time: " (format-time-string "%Y/%m/%d %H:%M:%S" now) 'timeclock-history (format-time-string "%Y/%m/%d %H:%M:%S" now)) (format-time-string "%Y/%m/%d %H:%M:%S" now)) (or (and project (stringp project) (> (length project) 0) (concat " " project)) "") "\n") (if (equal (downcase code) "o") (setq timeclock-last-period (- (timeclock-time-to-seconds now) (timeclock-time-to-seconds (cadr timeclock-last-event))) timeclock-discrepancy (+ timeclock-discrepancy timeclock-last-period))) (setq timeclock-last-event (list code now project))) (save-buffer) (run-hooks 'timeclock-event-hook) ;; APA: Don't kill buffer to avoid having to read in (potentially ;; encrypted) file. ;; (kill-buffer (current-buffer)) )) (defvar timeclock-moment-regexp (concat "\\([bhioO]\\)\\s-+" "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)\\s-+" "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)[ \t]*" "\\([^\n]*\\)")) (defsubst timeclock-read-moment () "Read the moment under point from the timelog." (cond ((looking-at timeclock-moment-regexp) (let ((code (match-string 1)) (year (string-to-number (match-string 2))) (mon (string-to-number (match-string 3))) (mday (string-to-number (match-string 4))) (hour (string-to-number (match-string 5))) (min (string-to-number (match-string 6))) (sec (string-to-number (match-string 7))) (project (match-string 8))) (list code (encode-time sec min hour mday mon year) project))) ((not (eobp)) (error "unexpected data in %s: %s" timeclock-file (buffer-substring (point-at-bol) (point-at-eol)))))) (defun timeclock-last-period (&optional moment) "Return the value of the last event period. If the last event was a clock-in, the period will be open ended, and growing every second. Otherwise, it is a fixed amount which has been recorded to disk. If MOMENT is non-nil, use that as the current time. This is only provided for coherency when used by `timeclock-discrepancy'." (if (equal (car timeclock-last-event) "i") (- (timeclock-time-to-seconds (or moment (current-time))) (timeclock-time-to-seconds (cadr timeclock-last-event))) timeclock-last-period)) (defsubst timeclock-entry-length (entry) (- (timeclock-time-to-seconds (cadr entry)) (timeclock-time-to-seconds (car entry)))) (defsubst timeclock-entry-begin (entry) (car entry)) (defsubst timeclock-entry-end (entry) (cadr entry)) (defsubst timeclock-entry-project (entry) (nth 2 entry)) (defsubst timeclock-entry-comment (entry) (nth 3 entry)) (defsubst timeclock-entry-list-length (entry-list) (let ((length 0)) (while entry-list (setq length (+ length (timeclock-entry-length (car entry-list)))) (setq entry-list (cdr entry-list))) length)) (defsubst timeclock-entry-list-begin (entry-list) (timeclock-entry-begin (car entry-list))) (defsubst timeclock-entry-list-end (entry-list) (timeclock-entry-end (car (last entry-list)))) (defsubst timeclock-entry-list-span (entry-list) (- (timeclock-time-to-seconds (timeclock-entry-list-end entry-list)) (timeclock-time-to-seconds (timeclock-entry-list-begin entry-list)))) (defsubst timeclock-entry-list-break (entry-list) (- (timeclock-entry-list-span entry-list) (timeclock-entry-list-length entry-list))) (defsubst timeclock-entry-list-projects (entry-list) (let (projects) (while entry-list (let ((project (timeclock-entry-project (car entry-list)))) (if projects (add-to-list 'projects project) (setq projects (list project)))) (setq entry-list (cdr entry-list))) projects)) (defsubst timeclock-day-required (day) (or (car day) timeclock-workday)) (defsubst timeclock-day-length (day) (timeclock-entry-list-length (cdr day))) (defsubst timeclock-day-debt (day) (- (timeclock-day-required day) (timeclock-day-length day))) (defsubst timeclock-day-begin (day) (timeclock-entry-list-begin (cdr day))) (defsubst timeclock-day-end (day) (timeclock-entry-list-end (cdr day))) (defsubst timeclock-day-span (day) (timeclock-entry-list-span (cdr day))) (defsubst timeclock-day-break (day) (timeclock-entry-list-break (cdr day))) (defsubst timeclock-day-projects (day) (timeclock-entry-list-projects (cdr day))) (defmacro timeclock-day-list-template (func) `(let ((length 0)) (while day-list (setq length (+ length (,(eval func) (car day-list)))) (setq day-list (cdr day-list))) length)) (defun timeclock-day-list-required (day-list) (timeclock-day-list-template 'timeclock-day-required)) (defun timeclock-day-list-length (day-list) (timeclock-day-list-template 'timeclock-day-length)) (defun timeclock-day-list-debt (day-list) (timeclock-day-list-template 'timeclock-day-debt)) (defsubst timeclock-day-list-begin (day-list) (timeclock-day-begin (car day-list))) (defsubst timeclock-day-list-end (day-list) (timeclock-day-end (car (last day-list)))) (defun timeclock-day-list-span (day-list) (timeclock-day-list-template 'timeclock-day-span)) (defun timeclock-day-list-break (day-list) (timeclock-day-list-template 'timeclock-day-break)) (defun timeclock-day-list-projects (day-list) (let (projects) (while day-list (let ((projs (timeclock-day-projects (car day-list)))) (while projs (if projects (add-to-list 'projects (car projs)) (setq projects (list (car projs)))) (setq projs (cdr projs)))) (setq day-list (cdr day-list))) projects)) (defsubst timeclock-current-debt (&optional log-data) (nth 0 (or log-data (timeclock-log-data)))) (defsubst timeclock-day-alist (&optional log-data) (nth 1 (or log-data (timeclock-log-data)))) (defun timeclock-day-list (&optional log-data) (let ((alist (timeclock-day-alist log-data)) day-list) (while alist (setq day-list (cons (cdar alist) day-list) alist (cdr alist))) day-list)) (defsubst timeclock-project-alist (&optional log-data) (nth 2 (or log-data (timeclock-log-data)))) (defun timeclock-log-data (&optional recent-only filename) "Return the contents of the timelog file, in a useful format. If the optional argument RECENT-ONLY is non-nil, only show the contents from the last point where the time debt (see below) was set. If the optional argument FILENAME is non-nil, it is used instead of the file specified by `timeclock-file.' A timelog contains data in the form of a single entry per line. Each entry has the form: CODE YYYY/MM/DD HH:MM:SS [COMMENT] CODE is one of: b, h, i, o or O. COMMENT is optional when the code is i, o or O. The meanings of the codes are: b Set the current time balance, or \"time debt\". Useful when archiving old log data, when a debt must be carried forward. The COMMENT here is the number of seconds of debt. h Set the required working time for the given day. This must be the first entry for that day. The COMMENT in this case is the number of hours in this workday. Floating point amounts are allowed. i Clock in. The COMMENT in this case should be the name of the project worked on. o Clock out. COMMENT is unnecessary, but can be used to provide a description of how the period went, for example. O Final clock out. Whatever project was being worked on, it is now finished. Useful for creating summary reports. When this function is called, it will return a data structure with the following format: (DEBT ENTRIES-BY-DAY ENTRIES-BY-PROJECT) DEBT is a floating point number representing the number of seconds \"owed\" before any work was done. For a new file (one without a 'b' entry), this is always zero. The two entries lists have similar formats. They are both alists, where the CAR is the index, and the CDR is a list of time entries. For ENTRIES-BY-DAY, the CAR is a textual date string, of the form YYYY/MM/DD. For ENTRIES-BY-PROJECT, it is the name of the project worked on, or t for the default project. The CDR for ENTRIES-BY-DAY is slightly different than for ENTRIES-BY-PROJECT. It has the following form: (DAY-LENGTH TIME-ENTRIES...) For ENTRIES-BY-PROJECT, there is no DAY-LENGTH member. It is simply a list of TIME-ENTRIES. Note that if DAY-LENGTH is nil, it means whatever is the default should be used. A TIME-ENTRY is a recorded time interval. It has the following format \(although generally one does not have to manipulate these entries directly; see below): (BEGIN-TIME END-TIME PROJECT [COMMENT] [FINAL-P]) Anyway, suffice it to say there are a lot of structures. Typically the user is expected to manipulate to the day(s) or project(s) that he or she wants, at which point the following helper functions may be used: timeclock-day-required timeclock-day-length timeclock-day-debt timeclock-day-begin timeclock-day-end timeclock-day-span timeclock-day-break timeclock-day-projects timeclock-day-list-required timeclock-day-list-length timeclock-day-list-debt timeclock-day-list-begin timeclock-day-list-end timeclock-day-list-span timeclock-day-list-break timeclock-day-list-projects timeclock-entry-length timeclock-entry-begin timeclock-entry-end timeclock-entry-project timeclock-entry-comment timeclock-entry-list-length timeclock-entry-list-begin timeclock-entry-list-end timeclock-entry-list-span timeclock-entry-list-break timeclock-entry-list-projects A few comments should make the use of the above functions obvious: `required' is the amount of time that must be spent during a day, or sequence of days, in order to have no debt. `length' is the actual amount of time that was spent. `debt' is the difference between required time and length. A negative debt signifies overtime. `begin' is the earliest moment at which work began. `end' is the final moment work was done. `span' is the difference between begin and end. `break' is the difference between span and length. `project' is the project that was worked on, and `projects' is a list of all the projects that were worked on during a given period. `comment', where it applies, could mean anything. There are a few more functions available, for locating day and entry lists: timeclock-day-alist LOG-DATA timeclock-project-alist LOG-DATA timeclock-current-debt LOG-DATA See the documentation for the given function if more info is needed." (let* ((log-data (list 0.0 nil nil)) (now (current-time)) (todays-date (timeclock-time-to-date now)) last-date-limited last-date-seconds last-date (line 0) last beg day entry event) (with-temp-buffer (insert-buffer (timeclock-get-timeclock-file-buffer (or filename timeclock-file))) (when recent-only (goto-char (point-max)) (unless (re-search-backward "^b\\s-+" nil t) (goto-char (point-min)))) (while (or (setq event (timeclock-read-moment)) (and beg (not last) (setq last t event (list "o" now)))) (setq line (1+ line)) (cond ((equal (car event) "b") (setcar log-data (string-to-number (nth 2 event)))) ((equal (car event) "h") (setq last-date-limited (timeclock-time-to-date (cadr event)) last-date-seconds (* (string-to-number (nth 2 event)) 3600.0))) ((equal (car event) "i") (if beg (error "Error in format of timelog file, line %d" line) (setq beg t)) (setq entry (list (cadr event) nil (and (> (length (nth 2 event)) 0) (nth 2 event)))) (let ((date (timeclock-time-to-date (cadr event)))) (if (and last-date (not (equal date last-date))) (progn (setcar (cdr log-data) (cons (cons last-date day) (cadr log-data))) (setq day (list (and last-date-limited last-date-seconds)))) (unless day (setq day (list (and last-date-limited last-date-seconds))))) (setq last-date date last-date-limited nil))) ((equal (downcase (car event)) "o") (if (not beg) (error "Error in format of timelog file, line %d" line) (setq beg nil)) (setcar (cdr entry) (cadr event)) (let ((desc (and (> (length (nth 2 event)) 0) (nth 2 event)))) (if desc (nconc entry (list (nth 2 event)))) (if (equal (car event) "O") (nconc entry (if desc (list t) (list nil t)))) (nconc day (list entry)) (setq desc (nth 2 entry)) (let ((proj (assoc desc (nth 2 log-data)))) (if (null proj) (setcar (cddr log-data) (cons (cons desc (list entry)) (car (cddr log-data)))) (nconc (cdr proj) (list entry))))))) (forward-line)) (if day (setcar (cdr log-data) (cons (cons last-date day) (cadr log-data)))) log-data))) (defun timeclock-find-discrep () "Calculate time discrepancies, in seconds. The result is a three element list, containing the total time discrepancy, today's discrepancy, and the time worked today." ;; This is not implemented in terms of the functions above, because ;; it's a bit wasteful to read all of that data in, just to throw ;; away more than 90% of the information afterwards. ;; ;; If it were implemented using those functions, it would look ;; something like this: ;; (let ((days (timeclock-day-alist (timeclock-log-data))) ;; (total 0.0)) ;; (while days ;; (setq total (+ total (- (timeclock-day-length (cdar days)) ;; (timeclock-day-required (cdar days)))) ;; days (cdr days))) ;; total) (let* ((now (current-time)) (todays-date (timeclock-time-to-date now)) ;; XEmacs change (first t) (accum 0) (elapsed 0) (line 0) event beg last-date avg last-date-limited last-date-seconds) (unless timeclock-discrepancy (when (file-readable-p timeclock-file) (setq timeclock-project-list nil timeclock-last-project nil timeclock-reason-list nil timeclock-elapsed 0) (with-temp-buffer (insert-buffer (timeclock-get-timeclock-file-buffer timeclock-file)) (goto-char (point-max)) (unless (re-search-backward "^b\\s-+" nil t) (goto-char (point-min))) (while (setq event (timeclock-read-moment)) ;; XEmacs change (setq line (1+ line)) (cond ((equal (car event) "b") (setq accum (string-to-number (nth 2 event)))) ((equal (car event) "h") (setq last-date-limited (timeclock-time-to-date (cadr event)) last-date-seconds (* (string-to-number (nth 2 event)) 3600.0))) ((equal (car event) "i") (when (and (nth 2 event) (> (length (nth 2 event)) 0)) (add-to-list 'timeclock-project-list (nth 2 event)) (setq timeclock-last-project (nth 2 event))) (let ((date (timeclock-time-to-date (cadr event)))) (if (if last-date (not (equal date last-date)) first) (setq first nil accum (- accum (if last-date-limited last-date-seconds timeclock-workday)))) (setq last-date date last-date-limited nil) (if beg ;; XEmacs change (error "Error in format of timelog file, line %d" line) (setq beg (timeclock-time-to-seconds (cadr event)))))) ((equal (downcase (car event)) "o") (if (and (nth 2 event) (> (length (nth 2 event)) 0)) (add-to-list 'timeclock-reason-list (nth 2 event))) (if (not beg) ;; XEmacs change (error "Error in format of timelog file, line %d" line) (setq timeclock-last-period (- (timeclock-time-to-seconds (cadr event)) beg) accum (+ timeclock-last-period accum) beg nil)) (if (equal last-date todays-date) (setq timeclock-elapsed (+ timeclock-last-period timeclock-elapsed))))) (setq timeclock-last-event event timeclock-last-event-workday (if (equal (timeclock-time-to-date now) last-date-limited) last-date-seconds timeclock-workday)) (forward-line)) (setq timeclock-discrepancy accum)))) (unless timeclock-last-event-workday (setq timeclock-last-event-workday timeclock-workday)) (setq accum (or timeclock-discrepancy 0) elapsed (or timeclock-elapsed elapsed)) (if timeclock-last-event (if (equal (car timeclock-last-event) "i") (let ((last-period (timeclock-last-period now))) (setq accum (+ accum last-period) elapsed (+ elapsed last-period))) (if (not (equal (timeclock-time-to-date (cadr timeclock-last-event)) (timeclock-time-to-date now))) (setq accum (- accum timeclock-last-event-workday))))) (list accum (- elapsed timeclock-last-event-workday) elapsed))) ;;; A reporting function that uses timeclock-log-data (defun timeclock-day-base (&optional time) "Given a time within a day, return 0:0:0 within that day. If optional argument TIME is non-nil, use that instead of the current time." (let ((decoded (decode-time (or time (current-time))))) (setcar (nthcdr 0 decoded) 0) (setcar (nthcdr 1 decoded) 0) (setcar (nthcdr 2 decoded) 0) (apply 'encode-time decoded))) (defun timeclock-geometric-mean (l) "Compute the geometric mean of the values in the list L." (let ((total 0) (count 0)) (while l (setq total (+ total (car l)) count (1+ count) l (cdr l))) (if (> count 0) (/ total count) 0))) (defun timeclock-generate-report (&optional html-p) "Generate a summary report based on the current timelog file. By default, the report is in plain text, but if the optional argument HTML-P is non-nil, HTML markup is added." (interactive) (let ((log (timeclock-log-data)) (today (timeclock-day-base))) (if html-p (insert "

    ")) (insert "Currently ") (let ((project (nth 2 timeclock-last-event)) (begin (nth 1 timeclock-last-event)) done) (if (timeclock-currently-in-p) (insert "IN") (if (or (null project) (= (length project) 0)) (progn (insert "Done Working Today") (setq done t)) (insert "OUT"))) (unless done (insert " since " (format-time-string "%Y/%m/%d %-I:%M %p" begin)) (if html-p (insert "
    \n") (insert "\n*")) (if (timeclock-currently-in-p) (insert "Working on ")) (if html-p (insert project "
    \n") (insert project "*\n")) (let ((proj-data (cdr (assoc project (timeclock-project-alist log)))) (two-weeks-ago (timeclock-seconds-to-time (- (timeclock-time-to-seconds today) (* 2 7 24 60 60)))) two-week-len today-len) (while proj-data (if (not (time-less-p (timeclock-entry-begin (car proj-data)) today)) (setq today-len (timeclock-entry-list-length proj-data) proj-data nil) (if (and (null two-week-len) (not (time-less-p (timeclock-entry-begin (car proj-data)) two-weeks-ago))) (setq two-week-len (timeclock-entry-list-length proj-data))) (setq proj-data (cdr proj-data)))) (if (null two-week-len) (setq two-week-len today-len)) (if html-p (insert "

    ")) (if today-len (insert "\nTime spent on this task today: " (timeclock-seconds-to-string today-len) ". In the last two weeks: " (timeclock-seconds-to-string two-week-len)) (if two-week-len (insert "\nTime spent on this task in the last two weeks: " (timeclock-seconds-to-string two-week-len)))) (if html-p (insert "
    ")) (insert "\n" (timeclock-seconds-to-string (timeclock-workday-elapsed)) " worked today, " (timeclock-seconds-to-string (timeclock-workday-remaining)) " remaining, done at " (timeclock-when-to-leave-string) "\n"))) (if html-p (insert "

    ")) (insert "\nThere have been " (number-to-string (length (timeclock-day-alist log))) " days of activity, starting " (caar (last (timeclock-day-alist log)))) (if html-p (insert "

    ")) (when html-p (insert "


    ") (let* ((day-list (timeclock-day-list)) (thirty-days-ago (timeclock-seconds-to-time (- (timeclock-time-to-seconds today) (* 30 24 60 60)))) (three-months-ago (timeclock-seconds-to-time (- (timeclock-time-to-seconds today) (* 90 24 60 60)))) (six-months-ago (timeclock-seconds-to-time (- (timeclock-time-to-seconds today) (* 180 24 60 60)))) (one-year-ago (timeclock-seconds-to-time (- (timeclock-time-to-seconds today) (* 365 24 60 60)))) (time-in (vector (list t) (list t) (list t) (list t) (list t))) (time-out (vector (list t) (list t) (list t) (list t) (list t))) (breaks (vector (list t) (list t) (list t) (list t) (list t))) (workday (vector (list t) (list t) (list t) (list t) (list t))) (lengths (vector '(0 0) thirty-days-ago three-months-ago six-months-ago one-year-ago))) ;; collect statistics from complete timelog (while day-list (let ((i 0) (l 5)) (while (< i l) (unless (time-less-p (timeclock-day-begin (car day-list)) (aref lengths i)) (let ((base (timeclock-time-to-seconds (timeclock-day-base (timeclock-day-begin (car day-list)))))) (nconc (aref time-in i) (list (- (timeclock-time-to-seconds (timeclock-day-begin (car day-list))) base))) (let ((span (timeclock-day-span (car day-list))) (len (timeclock-day-length (car day-list))) (req (timeclock-day-required (car day-list)))) ;; If the day's actual work length is less than ;; 70% of its span, then likely the exit time ;; and break amount are not worthwhile adding to ;; the statistic (when (and (> span 0) (> (/ (float len) (float span)) 0.70)) (nconc (aref time-out i) (list (- (timeclock-time-to-seconds (timeclock-day-end (car day-list))) base))) (nconc (aref breaks i) (list (- span len)))) (if req (setq len (+ len (- timeclock-workday req)))) (nconc (aref workday i) (list len))))) (setq i (1+ i)))) (setq day-list (cdr day-list))) ;; average statistics (let ((i 0) (l 5)) (while (< i l) (aset time-in i (timeclock-geometric-mean (cdr (aref time-in i)))) (aset time-out i (timeclock-geometric-mean (cdr (aref time-out i)))) (aset breaks i (timeclock-geometric-mean (cdr (aref breaks i)))) (aset workday i (timeclock-geometric-mean (cdr (aref workday i)))) (setq i (1+ i)))) ;; Output the HTML table (insert "\n") (insert "\n") (let ((i 0) (l 5)) (while (< i l) (insert "\n") (setq i (1+ i)))) (insert "\n") (insert "\n") (insert "\n") (let ((i 0) (l 5)) (while (< i l) (insert "\n") (setq i (1+ i)))) (insert "\n") (insert "\n") (insert "\n") (let ((i 0) (l 5)) (while (< i l) (insert "\n") (setq i (1+ i)))) (insert "\n") (insert "\n") (insert "\n") (let ((i 0) (l 5)) (while (< i l) (insert "\n") (setq i (1+ i)))) (insert "\n")) (insert "
    Statistics Entire -30 days -3 mons -6 mons -1 year
    Time in" (timeclock-seconds-to-string (aref time-in i)) "
    Time out" (timeclock-seconds-to-string (aref time-out i)) "
    Break" (timeclock-seconds-to-string (aref breaks i)) "
    Workday" (timeclock-seconds-to-string (aref workday i)) "
    These are approximate figures
    "))))) ;;; A helpful little function (defun timeclock-visit-timelog () "Open the file named by `timeclock-file' in another window." (interactive) (switch-to-buffer-other-window (timeclock-get-timeclock-file-buffer timeclock-file))) (provide 'timeclock) (run-hooks 'timeclock-load-hook) ;; make sure we know the list of reasons, projects, and have computed ;; the last event and current discrepancy. (if (file-readable-p timeclock-file) (timeclock-reread-log)) ;;; arch-tag: a0be3377-deb6-44ec-b9a2-a7be28436a40 ;;; timeclock.el ends here ;; ;; Local Variables: ;; indent-tabs-mode: t ;; tab-width: 8 ;; End: planner-el/planner-accomplishments.el000066400000000000000000000204731226462314700203000ustar00rootroot00000000000000;;; planner-accomplishments.el --- Accomplishment reports for planner.el ;; Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Filename: planner-accomplishments.el ;; Keywords: hypermedia ;; Author: Sandra Jean Chua (Sacha) ;; Description: Produce accomplishment reports for planner.el ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; planner-accomplishments.el produces accomplishment reports for ;; planner files. On date pages, it summarizes tasks by associated PlanPage. ;; ;; DISPLAYING A TEMPORARY BUFFER ;; ;; You can call `planner-accomplishments-show' to display a buffer ;; containing the current page's accomplishment report. ;; ;; REWRITING SECTIONS OF YOUR PLANNER ;; ;; Choose this approach if you want accomplishment reports to be in ;; their own section and you would like them to be readable in your ;; plain text files even outside Emacs. Caveat: The accomplishment ;; section should already exist in your template and will be rewritten ;; when updated. ;; ;; To use, set `planner-accomplishments-section' to the name of the ;; section to rewrite (default: "Accomplishments"). If you want ;; rewriting to be automatically performed, call ;; `planner-accomplishments-insinuate'. The accomplishments will be ;; rewritten whenever you save a planner page. If you want rewriting ;; to be manual, call `planner-accomplishments-update'. ;; ;; TODO ;; ;; - On plan pages, it summarizes tasks by associated date page ;; (controlled by `planner-accomplishments-plan-page-days'). Tasks ;; are broken down by status. (require 'planner) ;;; Code: ;;; USER VARIABLES ----------------------------------------------------------- (defgroup planner-accomplishments nil "Accomplishment reports for planner.el." :prefix "planner-accomplishments" :group 'planner) (defcustom planner-accomplishments-section "Accomplishments" "Header for the accomplishments section in a plan page." :type 'string :group 'planner-accomplishments) (defcustom planner-accomplishments-status-display '(("_" . "Unfinished") ("o" . "In progress") ("D" . "Delegated") ("P" . "Postponed") ("X" . "Completed") ("C" . "Cancelled")) "Alist of status-label maps also defining the order of display." :type '(alist :key-type string :value-type string) :group 'planner-accomplishments) (defvar planner-accomplishments-buffer "*Planner Accomplishments*" "Buffer name for accomplishment reports from `planner-accomplishments-show'.") ;;;###autoload (defun planner-accomplishments-insinuate () "Automatically call `planner-accomplishments-update'." (add-hook 'planner-mode-hook (lambda () (add-hook (if (and (boundp 'write-file-functions) (not (featurep 'xemacs))) 'write-file-functions 'write-file-hooks) 'planner-accomplishments-update nil t)))) ;;;###autoload (defun planner-accomplishments-update () "Update `planner-accomplishments-section'." (interactive) (save-excursion (save-restriction (when (planner-narrow-to-section planner-accomplishments-section) (delete-region (point-min) (point-max)) (insert "* " planner-accomplishments-section "\n\n" (planner-accomplishments-format-table (planner-accomplishments-extract-data)) "\n") nil)))) ; Return nil for write-file-functions ;;;###autoload (defun planner-accomplishments-show () "Display a buffer with the current page's accomplishment report." (interactive) (let ((page (and (planner-derived-mode-p 'planner-mode) (planner-page-name))) (data (planner-accomplishments-extract-data))) (when page (set-buffer (get-buffer-create planner-accomplishments-buffer)) (cd (planner-directory)) (setq muse-current-project (muse-project planner-project)) (planner-mode) (erase-buffer) (insert "Accomplishment report for " (planner-make-link page) "\n\n" (planner-accomplishments-format-table data) "\n") (goto-char (point-min)) (display-buffer (get-buffer-create planner-accomplishments-buffer) t)))) (defun planner-accomplishments-extract-data () "Return a list of ((link . status) . count) for tasks on the current page." (save-excursion (save-restriction (widen) (goto-char (point-min)) (let (results) (while (re-search-forward planner-task-regexp nil t) (let* ((info (planner-current-task-info)) (key (cons (planner-task-link info) (planner-task-status info))) (entry (assoc key results))) (if entry (setcdr entry (1+ (cdr entry))) (setq results (cons (cons key 1) results))))) results)))) (defun planner-accomplishments-total-by-link (data) "Return a list of (link . total)." (let (results) (mapcar (lambda (item) (let ((entry (assoc (car (car item)) results))) (if entry (setcdr entry (+ (cdr entry) (cdr item))) (setq results (cons (cons (car (car item)) (cdr item)) results))))) data) results)) (defun planner-accomplishments-total-by-status (data) "Return a list of (status . total)." (let (results) (mapcar (lambda (item) (let ((entry (assoc (cdr (car item)) results))) (if entry (setcdr entry (+ (cdr entry) (cdr item))) (setq results (cons (cons (cdr (car item)) (cdr item)) results))))) data) results)) (defun planner-accomplishments-format-table (data) "Format DATA from `planner-accomplishments-extract-data' into a table." (let ((links (planner-accomplishments-total-by-link data)) (status (planner-accomplishments-total-by-status data)) (page-format "%-30.30s") displayed-status) (setq links (sort links (lambda (a b) (> (cdr a) (cdr b))))) ;; Determine the status to be displayed (with-temp-buffer (insert (format page-format "Link")) (mapcar (lambda (s) (when (assoc (car s) status) (insert " | " (cdr s)) (setq displayed-status (cons (cons (car s) (format "%%%dd" (length (cdr s)))) displayed-status)))) planner-accomplishments-status-display) (insert " | Total\n") (setq displayed-status (nreverse displayed-status)) (mapcar (lambda (page) (insert (if (car page) (let ((len (length (car page))) (link (planner-make-link (car page)))) (if (< len 30) (concat link (make-string (- 30 len) ?\ )) link)) "nil")) (mapcar (lambda (s) (insert (format (concat " | " (cdr s)) (or (cdr (assoc (cons (car page) (car s)) data)) 0)))) displayed-status) (insert (format " | %5d\n" (cdr page)))) links) (insert (format page-format "Total")) (let ((count 0)) (mapcar (lambda (s) (setq count (+ count (cdr (assoc (car s) status)))) (insert (format (concat " | " (cdr s)) (cdr (assoc (car s) status))))) displayed-status) (insert (format " | %5d\n" count))) (buffer-string)))) (provide 'planner-accomplishments) ;;; planner-accomplishments.el ends here planner-el/planner-appt.el000066400000000000000000001644541226462314700160630ustar00rootroot00000000000000;;; planner-appt.el --- appointment alerts from planner ;; ;; ;; Copyright (C) 2005, 2006, 2007, 2008 Jim Ottaway ;; Copyright (C) 2005, 2008 Henrik S. Hansen ;; Parts copyright (C) 2005, 2006, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Seth Falcon ;; ;; Author: Jim Ottaway ;; Keywords: hypermedia ;; ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;; ;; Please report any bugs that you come across to the authors at the ;; addresses given above. ;; ;; Usage: ;; ;; Add "(planner-appt-insinuate)" to your configuration to make ;; Planner work with appt. ;; ;; See the Appointments section of the Planner manual for further ;; details. ;; ;; Contributors: ;; ;; * Seth Falcon supplied the idea and the code that is the basis of ;; the forthcoming appointments display functionality. ;; ;;; TODO: ;; ;; * Correct sorting of task appointments ;; ;; * Consider changing "insinuate" into "install". I don't like the ;; word "insinuate" very much! Or a minor mode perhaps: ;; planner-appt-minor-mode ;; ;; * A lot of the code properly belongs elsewhere: schedule sorting, ;; schedule cyclical entries, calendar marking... ;; ;;; Code: (require 'planner) (require 'appt) (require 'calendar) ;;; Customization (defgroup planner-appt nil "Appointment integration for planner.el." :prefix "planner-appt-" :group 'planner) (defcustom planner-appt-schedule-section "Schedule" "The name of the section where the schedule is to be found." :group 'planner-appt :type 'string) (defcustom planner-appt-font-lock-appointments-flag t "Non-nil means use font-locking for appointments." :group 'planner-appt :type '(choice (const :tag "Use font-locking" t) (const :tag "Don't use font-locking" nil))) (defcustom planner-appt-update-appts-on-save-flag nil "Non-nil means update appointment alerts on saving today's plan." :group 'planner-appt :type '(choice (const :tag "Update on save" t) (const :tag "Don't update on save" nil))) (defcustom planner-appt-sort-schedule-on-update-flag nil "Non-nil means sort the schedule when updating appointments." :group 'planner-appt :type '(choice (const :tag "Sort on update" t) (const :tag "Don't sort on update" nil))) (defcustom planner-appt-update-hook '() "Hook run after appointments have been updated." :group 'planner-appt :type 'hook) (defcustom planner-appt-schedule-cyclic-behaviour 'today "Determines the behaviour of cyclical schedule insertion. Used after `planner-appt-schedule-cyclic-insinuate' has been called. 'today means only add cylical schedule entries for today 'future means add cyclical entries for all future day pages visited." :group 'planner-appt :type '(choice (const :tag "For today only" today) (const :tag "For all future pages." future))) (defcustom planner-appt-alert-buffer "*Alerts*" "Name of the buffer for displaying active alerts. Used by `planner-appt-show-alerts'." :group 'planner-appt :type 'string) (defcustom planner-appt-task-use-appointments-section-flag nil "When non-nil, task appointments will be copied to an appoinments section. The section name is supplied by `planner-appt-task-appointments-section'." :group 'planner-appt :type 'boolean) (defcustom planner-appt-task-appointments-section "Schedule" "Name of the section where task appointments are copied. The copying is contingent upon `planner-appt-task-use-appointments-section-flag'." :group 'planner-appt :type 'string) (defcustom planner-appt-format-appt-section-line-function #'planner-appt-format-appt-section-line "The function used when formatting an appointment section line. This function should take one argument: an appointment description. The description is in the form used when an appointment alert is signalled: a string with the time of the appointment and some text such as \"12:00 Do something\". Look at the default function `planner-appt-format-appt-section-line' for inspiration if you want to make a different format." :group 'planner-appt :type 'function) (defcustom planner-appt-limit-highlighting-flag t "When non-nil, only highlight appointment times in tasks and the schedule. When nil, all appointment times are highlighted, wherever they may be in the buffer." :group 'planner-appt :type 'boolean) (defcustom planner-appt-forthcoming-days 7 "Number of days to look ahead for appointments." :group 'planner-appt :type 'integer) (defcustom planner-appt-forthcoming-appt-section "Forthcoming Appointments" "Title of the section for forthcoming appointments." :group 'planner-appt :type 'string) (defcustom planner-appt-forthcoming-show-day-names-flag t "When non nil, show day names in forthcoming appointments." :group 'planner-appt :type 'boolean) (defcustom planner-appt-forthcoming-repeat-date-string " " "String to insert for repeated dates. When there are multiple appointments for a date, the date is inserted in the first appointment and the others have this string in their date cell. If the string consists of anything other than whitespace, then a link to the day page for the appoinment is created." :group 'planner-appt :type 'string) (defcustom planner-appt-forthcoming-look-at-cyclic-flag nil "When non nil, add cyclic entries to the forthcoming appointments section." :group 'planner-appt :type 'boolean) ;; Regular Expressions ;; TODO: Should these really be customizable anyway? ;; TODO: Dynamically changing dependent customizations; i.e., if this ;; is changed, all the other time-based regexps should change too [I ;; don't understand customize well enough to do this]. (defcustom planner-appt-time-regexp "[0-9]?[0-9]:[0-5][0-9]\\(?:am\\|pm\\)?" "Regular expression matching times." :group 'planner-appt :type 'regexp) (defcustom planner-appt-task-regexp (concat "[@!][ \t]*\\(" planner-appt-time-regexp "\\)[ \t]*") "If a task description matches this regexp, it's an appointment. Match group 1 is the time of the appointment. Used with the task-based method. If you use schedules, look at `planner-appt-schedule-appt-regexp'." :group 'planner-appt :type 'regexp) (defcustom planner-appt-task-nagging-regexp (concat "![ \t]*\\(" planner-appt-time-regexp "\\)[ \t]*") "If a task description matches this regexp, it's a nagging appointment. Used with the task-based method. If you use schedules, look at `planner-appt-schedule-appt-regexp'." :group 'planner-appt :type 'regexp) (defcustom planner-appt-schedule-basic-regexp (concat "\\(" ;; the appointment time (match group 1) planner-appt-time-regexp "\\)" ;; possibly some space, possibly a |, and any amount of space "[ \t]*|?[ \t]*" ;; perhaps another time [the end time] (match group 2) "\\(" planner-appt-time-regexp "\\)?" ;; possibly some space or some ?' chars, possibly a |, and any ;; amount of space "[' \t]*|?[ \t]*" ;; the appointment text (match group 3) "\\(.+\\)") "Basic regular expression to match a schedule. Match group 1 should yield the start time, match group 2 the stop time, and match group 3 the schedule text." :group 'planner-appt) ;; NB: The groups are shifted in this regexp. (defcustom planner-appt-schedule-regexp (concat ;; any amount of whitespace possibly followed by @ and any amount ;; of whitespace "^[ \t]*\\(@?\\)[ \t]*" ;; followed by the basic regexp planner-appt-schedule-basic-regexp) "Regexp matching schedule entries. Match group 1 should match at most one leading instance of the appointment marker, Match group 2 should yield the start time, match group 3 the stop time, and match group 4 the schedule text." :group 'planner-appt :type 'regexp) (defcustom planner-appt-schedule-appt-regexp (concat ;; any amount of whitespace followed by @ and any amount of ;; whitespace "^[ \t]*@[ \t]*" ;; followed by the basic regexp planner-appt-schedule-basic-regexp) "Regexp matching appointments in the schedule requiring alerts. Used with the schedule-based method. If you use tasks for appointments, look at `planner-appt-task-regexp.' Match group 1 should yield the start time, match group 2 the stop time, and match group 3 the alert text." :group 'planner-appt :type 'regexp) ;;; Planner Miscellany ;; Could be useful elsewhere in planner? (defun planner-appt-todays-page-p () "Return t if the current page is today's, otherwise nil." (string= (planner-page-name) (planner-today))) (defun planner-appt-seek-to-end-of-current-section () "Go to the end of the current section." (goto-char (or (and (re-search-forward "^\\*[^*\n]" nil t) (1- (planner-line-beginning-position))) (point-max)))) (defvar planner-appt-write-file-hook (if (and (boundp 'write-file-functions) (not (featurep 'xemacs))) 'write-file-functions 'write-file-hooks) "The write file hook to use.") ;;; Planner-Appt Miscellany (defvar planner-appt-debug-buffer "*planner-appt debug messages*" "The buffer to put debugging messages from planner-appt.") (defvar planner-appt-debug-flag nil "Non-nil means turn on planner-appt debugging.") (defmacro planner-appt-debug (form &rest body) "Evaluate FORM if `planner-appt-debug-flag' is non-nil. Optional BODY is evaluated otherwise." `(if planner-appt-debug-flag ,form ,@body)) (defun planner-appt-debug-message (&rest args) "Insert ARGS into `planner-appt-debug-buffer'. This code runs only if `planner-appt-debug-flag' is non-nil." (planner-appt-debug (with-current-buffer (get-buffer-create planner-appt-debug-buffer) (goto-char (point-max)) (apply #'insert args) (insert ?\n)))) (defun planner-appt-earlier-than-now-p (time) "Return t if TIME is earlier than the current time. Time formats are those used by the appt appointment system." ;; From appt-check (let* ((now (decode-time)) (cur-hour (nth 2 now)) (cur-min (nth 1 now)) (cur-time (+ (* cur-hour 60) cur-min))) (> cur-time (appt-convert-time time)))) ;; Not used in this file, but added for completeness. (defun planner-appt-later-than-now-p (time) "Return t if TIME is later than the current time. Time formats are those used by the appt appointment system." ;; From appt-check (let* ((now (decode-time)) (cur-hour (nth 2 now)) (cur-min (nth 1 now)) (cur-time (+ (* cur-hour 60) cur-min))) (< cur-time (appt-convert-time time)))) (defvar --planner-appt-tasks-added-appts '() "Internal variable: Tracks added task-based appointment alerts.") (defvar --planner-appt-tasks-earlier-appts '() "Internal variable: Tracks appointments ignored because they were too early.") (defun planner-appt-clear-appts (appt-list) (while appt-list (setq appt-time-msg-list (delete (pop appt-list) appt-time-msg-list)))) (defun planner-appt-format-time-and-description (time description) "Format TIME [a string] and DESCRIPTION as an appointment." (concat time " " description)) (eval-and-compile (if (> emacs-major-version 21) (defun planner-appt-make-appt-element (time text) (list (list (appt-convert-time time)) (planner-appt-format-time-and-description time text) t)) (defun planner-appt-make-appt-element (time text) (list (list (appt-convert-time time)) (planner-appt-format-time-and-description time text))))) (defun planner-appt-remember-appt (time text list) "Store details of an appointment with TIME and TEXT in LIST. Return the new list." (push (planner-appt-make-appt-element time text) list)) (defun planner-appt-forget-appt (appt appt-list) "Remove APPT from APPT-LIST and return the new list. APPT is in the appt format." (delete (car (member appt appt-list)) appt-list)) (defun planner-appt-add-hook (hook function &optional append global) "Add to the value of HOOK the function FUNCTION. This is `add-hook' with local and global switched. FUNCTION is not added if already present. FUNCTION is added (if necessary) at the beginning of the hook list unless the optional argument APPEND is non-nil, in which case FUNCTION is added at the end. The optional fourth argument, GLOBAL, if non-nil, says to modify the hook's global value rather than its local value." (add-hook hook function append (not global))) (defun planner-appt-remove-task-id (description) (if (string-match (concat "\\s-*" (if (boundp 'planner-id-regexp) planner-id-regexp)) description) (replace-match "" t t description) description)) (defun planner-appt-format-description (description) (planner-appt-remove-task-id (planner-remove-links description))) ;;; Advice ;; for speedy enabling and disabling of advice: (defvar --planner-appt-advice '() "Internal variable: List of advices added by `planner-appt-defadvice'. Each element is a list of args for `ad-enable-advice' and `ad-disable-advice'.") (eval-and-compile (defvar planner-appt-advice-common-flags '(preactivate disable) "Advice flags common to all planner-appt advice.")) (defmacro planner-appt-defadvice (function args doc &rest body) "Advise FUNCTION with ARGS, DOC and BODY. Remembers the advice function and args in `--planner-appt-advice'." `(prog1 (defadvice ,function (,@args ,@planner-appt-advice-common-flags) ,doc ,@body) (let ((info '(,function ,(car args) ,(cadr args)))) (unless (member info --planner-appt-advice) (push info --planner-appt-advice))))) (put 'planner-appt-defadvice 'edebug-form-spec '(&define name (name name &rest sexp) stringp [&optional ("interactive" interactive)] def-body)) (put 'planner-appt-defadvice 'lisp-indent-function 'defun) ;; See what happened with the preactivation. (planner-appt-debug (progn (require 'trace) (trace-function-background 'ad-cache-id-verification-code "*planner-appt advice trace*"))) (defun planner-appt-disable-all-advice () "Disable all advice added with `planner-appt-defadvice'." (mapcar #'(lambda (args) (apply #'ad-disable-advice args) (ad-activate (car args))) --planner-appt-advice)) (defun planner-appt-enable-all-advice () "Enable all advice added with `planner-appt-defadvice'." (mapcar #'(lambda (args) (apply #'ad-enable-advice args) (ad-activate (car args))) --planner-appt-advice)) (defmacro with-planner-appt-task-advice-disabled (&rest body) "Evaluate BODY forms with all advice matching \"planner-appt-task\" disabled." `(unwind-protect (progn (planner-appt-disable-all-advice) (planner-appt-debug-message "all advice disabled") ,@body) (planner-appt-enable-all-advice) (planner-appt-debug-message "all advice enabled"))) (put 'with-planner-appt-task-advice-disabled 'lisp-indent-function 0) (put 'with-planner-appt-task-advice-disabled 'edebug-form-spec '(body)) ;;; Showing Appointments In Various Ways (defvar planner-appt-methods '() "Methods used for appointment alerts. Internal variable: to set up appointment methods use one of: `planner-appt-use-tasks' `planner-appt-use-schedule' `planner-appt-use-tasks-and-schedule'.") ;; Copying task appts over to an "Appointments" section. (defun planner-appt-format-appt-section-line (desc) "Format DESC as a line for the appointments section." (let* ((td (planner-appt-task-parse-task ;; Trick the function into parsing: (concat "@" desc))) (text (car td)) (time (cadr td)) (end-time (if (string-match (format "\\s-*\\(%s\\)\\s-*" planner-appt-time-regexp) text) (prog1 (match-string 1 text) (setq text (replace-match "" t t text))) " "))) ;; Format in the style of a tabular schedule. (format "%6s | %5s | %s" ;; Using an @ means the time gets fontified for free. (concat "@" time) end-time (if (string= planner-appt-task-appointments-section planner-appt-schedule-section) ;; To avoid confusion, add an indication that this ;; item came from a task. (concat "# " text) text)))) (defvar --planner-appt-lines-added-to-section '() "Internal variable: Remembers lines added by `planner-appt-update-appt-section' the last time it was called.") (defun planner-appt-task-schedule-item-p (string) "Return t if STRING is a schedule item derived from a task." (member string --planner-appt-lines-added-to-section)) ;; ;; Look for any property in the string since STRING will usually be ;; ;; derived from a buffer substring which may have been edited. ;; (text-property-any 0 (length string) 'appt-task t string)) (defun planner-appt-update-appt-section () (save-excursion (planner-seek-to-first planner-appt-task-appointments-section) (let ((bound (make-marker)) (lines-to-delete (copy-sequence --planner-appt-lines-added-to-section)) line) (save-excursion (planner-appt-seek-to-end-of-current-section) (set-marker bound (point))) (dolist (appt (append --planner-appt-tasks-added-appts --planner-appt-tasks-earlier-appts)) (setq line (funcall planner-appt-format-appt-section-line-function (cadr appt))) (setq lines-to-delete (delete line lines-to-delete)) (save-excursion (unless (search-forward line bound t) (insert line ?\n))) ;; Remember the line even if it was already there (push line --planner-appt-lines-added-to-section)) ;; Remove lines of deleted tasks (dolist (del-line lines-to-delete) (setq --planner-appt-lines-added-to-section (delete del-line --planner-appt-lines-added-to-section)) (save-excursion (when (search-forward del-line bound t) (replace-match "") (when (eq (char-after) ?\n) (delete-char 1))))) (set-marker bound nil)) ;; Use schedule sorting with some changes (let ((planner-appt-schedule-section planner-appt-task-appointments-section) (planner-appt-schedule-regexp (concat "\\(.*?\\)" ; to shift the match groups planner-appt-schedule-basic-regexp))) (planner-appt-schedule-sort)))) (defun planner-appt-update-appt-section-maybe () (when (and ;; The appointment section is only relevant if the task ;; method is used (memq 'tasks planner-appt-methods) planner-appt-task-use-appointments-section-flag) (with-planner-update-setup (save-excursion (with-planner-appt-task-advice-disabled (planner-goto-today)) (planner-appt-update-appt-section))))) (defmacro with-planner-appt-update-section-disabled (&rest body) `(let ((planner-appt-task-use-appointments-section-flag nil)) ,@body)) (put 'with-planner-appt-update-section-disabled 'lisp-indent-function 0) (put 'with-planner-appt-update-section-disabled 'edebug-form-spec '(body)) ;; Compatibility fix for Xemacs [and for Emacs <21?] (if (fboundp 'fit-window-to-buffer) (defalias 'planner-fit-window-to-buffer 'fit-window-to-buffer) (defalias 'planner-fit-window-to-buffer 'shrink-window-if-larger-than-buffer)) ;; Display Current Appointments (defun planner-appt-show-alerts () "Display a list of currently active alerts in another window." (interactive) (let ((buf (get-buffer-create planner-appt-alert-buffer))) (with-current-buffer buf (erase-buffer) (insert "Current alerts\n==============") (if appt-time-msg-list (dolist (appt appt-time-msg-list) (insert "\n" (cadr appt))) (insert "\nNone")) (goto-char (point-min))) (planner-fit-window-to-buffer (display-buffer buf)))) ;; Display/Insert Forthcoming Appointments (defvar planner-appt-forthcoming-regexp (concat "\\(" planner-appt-schedule-appt-regexp "\\)\\|\\(" planner-live-task-regexp planner-appt-task-regexp "\\)")) (defvar planner-appt-forthcoming-task-regexp (concat planner-live-task-regexp planner-appt-task-regexp)) (defun planner-appt-forthcoming-format-appt-description (time description) (funcall planner-appt-format-appt-section-line-function (planner-appt-format-time-and-description time (planner-appt-format-description description)))) (defun planner-appt-forthcoming-task-data (info) (let ((task-appt (planner-appt-task-parse-task (planner-task-description info)))) (when task-appt (cons (appt-convert-time (nth 1 task-appt)) (planner-appt-forthcoming-format-appt-description (nth 1 task-appt) (nth 0 task-appt)))))) (defun planner-appt-forthcoming-get-appts (n &optional include-today) (planner-save-buffers) (let ((appts '()) (pages (planner-get-day-pages (if include-today (planner-today) (planner-calculate-date-from-day-offset (planner-today) 1)) (planner-calculate-date-from-day-offset (planner-today) (if include-today n (1+ n))))) cyclic-data cyclic-task-descriptions line task-info task-data date-absolute date time text) ;; After scanning pages and [conditionally] cyclic entries, each ;; element of appts has: ;; ;; ( ;;

  • \\)\\(<&| [^<]*>\\)\\(.*\\)\\(\\)\\(
  • \\)" 3 planner-authz-fix-list-item)) "List of markup rules for publishing PLANNER with `planner-authz' restrictions. For more on the structure of this list, see `muse-publish-markup-regexps'." :group 'planner-authz :type '(repeat (choice (list :tag "Markup rule" integer (choice regexp symbol) integer (choice string function symbol)) function))) (defcustom planner-authz-markup-functions '((table . planner-authz-mason-markup-table)) "An alist of style types to custom functions for that kind of text." :group 'planner-authz :type '(alist :key-type symbol :value-type function)) (defcustom planner-authz-markup-tags '(("authz" t t nil planner-authz-tag) ("diary-section" t t nil planner-authz-diary-section-tag) ("note" t t nil planner-authz-note-tag) ("task" t t nil planner-authz-task-tag)) "A list of tag specifications for authorization markup." :group 'planner-authz :type '(repeat (list (string :tag "Markup tag") (boolean :tag "Expect closing tag" :value t) (boolean :tag "Parse attributes" :value nil) (boolean :tag "Nestable" :value nil) function))) (defcustom planner-authz-mason-markup-strings '((planner-authz-begin . "<&| authz.mas:content, 'users', [qw(%s)] &>") (planner-authz-begin-alt . "<&| authz.mas:content, 'users', [qw(%s)], 'alt', '%s' &>") (planner-authz-end . "") (planner-authz-page . "<& authz.mas:page, 'users', [qw(%s)] &>")) "Strings used for additing authorization controls. If a markup rule is not found here, `planner-html-markup-strings' is searched." :type '(alist :key-type symbol :value-type string) :group 'planner-authz) ;; Non-customizable variables (defvar planner-authz-pages nil "Alist of planner pages and users authorized to view them. The list of users is separated by spaces. This variable is internal to planner-authz; do not set it manually.") (defvar planner-authz-publishing-alist nil "Alist used by `planner-authz' to track published pages and their dependencies. This alist stores pages that have been published during the current publishing process, as (PAGENAME . t), and pages whose tasks and notes depend on those pages for access control, as (PAGENAME . nil). At the end of publishing, `planner-authz' uses this alist to determine which dependencies need to be republished, even if they themselves haven't changed.") (defvar planner-authz-disable-dependency-publishing nil "If non-nil, `planner-authz' will not republish unchanged pages whose tasks or notes depend on the page currently being published. Normally, linked pages are republished in case the access list for the current page has changed. This variable is set to t while `planner-authz' is republishing dependent pages to avoid indefinite recursion.") ;;; Functions (defun planner-authz-after-markup () "Remove the page currently being marked up from the queue of pages to republish and enforce default access controls for project pages." (let ((page (planner-page-name))) (when page (let ((cell (assoc page planner-authz-publishing-alist))) (if cell ;; if already t, the list is stale; whack it (if (cdr cell) (setq planner-authz-publishing-alist '(page . t))) (push '(page . t) planner-authz-publishing-alist))) (let ((users (planner-authz-users))) (when users (goto-char (point-min)) (planner-insert-markup (muse-markup-text 'planner-authz-page users)) (insert "\n")))))) (defun planner-authz-after-project-publish (project) "Republish pages that reference restricted pages and call the generate Mason code." (when (string= planner-project (car project)) (while planner-authz-publishing-alist (if (not (cdar planner-authz-publishing-alist)) (let ((planner-authz-disable-dependency-publishing t)) (muse-project-publish-file (caar planner-authz-publishing-alist) planner-project t))) (setq planner-authz-publishing-alist (cdr planner-authz-publishing-alist))) (run-hook-with-args 'planner-authz-after-publish-hook project))) (defun planner-authz-before-markup () "Process #authz directives when publishing only a single page. Mark planner page sections according to `planner-authz-sections-rule-list'." (planner-authz-markup-all-sections)) (defun planner-authz-day-p (&optional page) "Return non-nil if the current page or PAGE is a day page." (save-match-data (string-match planner-date-regexp (or page (planner-page-name))))) (defun planner-authz-default (page) "Return the default space-separated string of users that would apply to PAGE. Nil is always returned for day pages." (and planner-authz-project-default (not (planner-authz-day-p page)) ; not on day pages (mapconcat 'identity planner-authz-project-default " "))) (defun planner-authz-file-alist (users) "Generate a list of planner files that USERS have access to." (let ((pages (planner-file-alist)) result) (while pages (let (not-found-p) (with-temp-buffer (insert-file-contents-literally (cdar pages)) (when (re-search-forward "^#authz\\s-+\\(.+\\)\n+" nil t) (let ((users-iter users) (authz (split-string (match-string 1)))) (while (and users-iter (not not-found-p)) (unless (member (car users-iter) authz) (setq not-found-p t)) (setq users-iter (cdr users-iter))))) (unless not-found-p (setq result (append (list (car pages)) result)))) (setq pages (cdr pages)))) result)) (defun planner-authz-fix-list-item () "Rearrange list items restricted by `planner-authz' to avoid empty list items on the published page." (replace-match "\\2\\1\\3\\5\\4") (muse-publish-mark-read-only (match-beginning 0) (match-end 2)) (muse-publish-mark-read-only (match-beginning 4) (match-end 0))) (defun planner-authz-generate-mason-component (project) "Generate the Mason component restricting content. The component's name is taken from `planner-authz-mason-component-name' and initialized with the contents of `planner-authz-mason-component-contents'. The component restricts access to users specified by and #authz tags." (with-temp-buffer (insert planner-authz-mason-component-contents) (let ((backup-inhibited t) (styles (cddr project))) (while styles (let ((path (muse-style-element :path (car styles)))) (and path (string-match "mason" (muse-style-element :base (car styles))) (write-file (concat (file-name-directory path) planner-authz-mason-component-name)))) (setq styles (cdr styles)))))) (defun planner-authz-markup-section-predict (rule) "Check if the prediction is satisfied." (let ((predict (elt rule 1))) (if (functionp predict) (funcall predict) predict))) (defun planner-authz-markup-section () "Restrict section according to `planner-authz-sections-rule-list'." (let ((begin (planner-line-beginning-position)) (rule-list planner-authz-sections-rule-list) section-name section-level next-section-regexp) (goto-char begin) (save-match-data (re-search-forward planner-authz-sections-regexp nil t) (setq section-level (length (match-string 1))) (setq section-name (match-string 2))) (let ((rule (catch 'done (while rule-list (if (string-match (caar rule-list) section-name) (throw 'done (car rule-list)) (setq rule-list (cdr rule-list)))) nil))) (if (and rule (planner-authz-markup-section-predict rule)) (progn (goto-char begin) (muse-publish-surround-text (format "\n" (mapconcat 'identity (elt rule 2) " ")) "\n\n" (lambda () (save-match-data (let ((found nil)) (re-search-forward planner-authz-sections-regexp nil t) (while (and (not found) (re-search-forward planner-authz-sections-regexp nil t)) (if (<= (length (match-string 1)) section-level) (setq found t))) (if found (goto-char (planner-line-beginning-position)) (goto-char (point-max)))))))))))) (defun planner-authz-markup-all-sections () "Run `planner-authz-markup-section' on the entire buffer." (goto-char (point-min)) (while (re-search-forward planner-authz-sections-regexp nil t) (planner-authz-markup-section))) (defun planner-authz-mason-markup-table () "Protect \"<&|\" Mason constructs from Muse table markup." (let* ((beg (planner-line-beginning-position)) (style (muse-style-element :base (muse-style))) (base (if style (muse-style-element :base style))) (func (if base (muse-find-markup-element :functions 'table (muse-style-element :base base))))) (when (functionp func) (save-excursion (save-match-data (goto-char beg) (while (search-forward "<&|" (line-end-position) t) (replace-match "<&:" t t)))) (funcall func) (let ((end (point))) (goto-char beg) (while (search-forward "<&:" end t) (replace-match "<&|" t t)))))) (defun planner-authz-index-as-string (&optional as-list exclude-private) "Generate an index of all Muse pages with authorization controls. In the published index, only those links to pages which the remote user is authorized to access will be shown. If AS-LIST is non-nil, insert a dash and spaces before each item. If EXCLUDE-PRIVATE is non-nil, exclude files that have private permissions. If EXCLUDE-CURRENT is non-nil, exclude the current file from the output." (with-temp-buffer (insert (planner-index-as-string as-list exclude-private)) (when muse-publishing-p (goto-char (point-min)) (while (and (re-search-forward (if as-list (concat "^[" muse-regexp-blank "]+-[" muse-regexp-blank "]*") (concat "^[" muse-regexp-blank "]*")) nil t) (looking-at muse-explicit-link-regexp)) (let* ((link (buffer-substring (point) (line-end-position))) (page (planner-link-base link)) (users (if page (planner-authz-users page)))) (if users (progn (insert (format "" users)) (end-of-line) (insert "")) (end-of-line))))) (buffer-substring (point-min) (point-max)))) (defun planner-authz-republish-dependencies-maybe (linked-pages) "Remember LINKED-PAGES to be republished later. The pages will be republished if and only if the current page is restricted." (and (not planner-authz-disable-dependency-publishing) (planner-authz-users) (while linked-pages (unless (assoc (car linked-pages) planner-authz-publishing-alist) (push '(car linked-pages) planner-authz-publishing-alist)) (setq linked-pages (cdr linked-pages))))) (defun planner-authz-tag (beg end attrs) "Publish tags. The region from BEG to END is protected. ATTRS should be an alist of tag attributes including \"users\" and optionally \"alt\" for alternative text to be displayed to unauthorized users." (save-excursion (let ((alt (or (cdr (assoc "alt" attrs)) "")) (users (or (cdr (assoc "users" attrs)) ""))) (goto-char beg) (planner-insert-markup (if (zerop (length alt)) (muse-markup-text 'planner-authz-begin users) (muse-markup-text 'planner-authz-begin-alt users alt))) (goto-char end) (planner-insert-markup (muse-markup-text 'planner-authz-end))))) (defun planner-authz-diary-section-tag (beg end attrs) "Restrict entries in a diary section." (save-excursion (save-restriction (narrow-to-region beg end) (planner-publish-nested-section-tag beg end) (goto-char beg) (while (and (zerop (forward-line)) (= (point) (planner-line-beginning-position))) (unless (looking-at "^\\(?:[ \t]*\\|No entries\\|

    \\)$") (let ((line-begin (point)) (line-end (line-end-position))) (re-search-forward planner-authz-link-regexp line-end t) (let* ((link (match-string 1)) (linked-pages (if link (mapcar 'planner-link-base (if (featurep 'planner-multi) (planner-multi-split link) link)))) (linked-users (if linked-pages (planner-authz-multi-users linked-pages) (and planner-authz-day-task-default (mapconcat 'identity planner-authz-day-task-default " "))))) (when linked-users (if (and planner-authz-appt-alt planner-authz-appt-regexp (progn (goto-char line-begin) (re-search-forward planner-authz-appt-regexp line-end t))) (progn (search-forward " - " (+ 2 (point)) t) (planner-insert-markup (muse-markup-text 'planner-authz-begin-alt linked-users planner-authz-appt-alt))) (planner-insert-markup (muse-markup-text 'planner-authz-begin linked-users))) (end-of-line) (planner-insert-markup (muse-markup-text 'planner-authz-end)))))))))) (defun planner-authz-note-tag (beg end attrs) "Restrict notes linked to a restricted page. If this page is restricted and the note is linked to another page, remember to republish that page later and restrict the note as it appears there. Call `planner-publish-note-tag' as a side effect." (save-excursion (save-restriction (narrow-to-region beg end) (planner-publish-note-tag beg end attrs) (let* ((categories (cdr (assoc "categories" attrs))) (links (if (or (not categories) (zerop (length categories))) (cdr (assoc "link" attrs)) categories)) (linked-pages (if (and links (not (zerop (length links)))) (mapcar 'planner-link-base (if (featurep 'planner-multi) (planner-multi-split links) links)))) (linked-users (if linked-pages (planner-authz-multi-users linked-pages) (and planner-authz-day-note-default (planner-authz-day-p) (mapconcat 'identity planner-authz-day-note-default " "))))) ;; If this note is linked to another page, republish that page ;; later to restrict the note as it appears there, providing that ;; page has an authz restriction (if linked-pages (planner-authz-republish-dependencies-maybe linked-pages)) ;; If the linked page has an authz restriction, restrict this note (when linked-users (goto-char (point-min)) (planner-insert-markup (muse-markup-text 'planner-authz-begin linked-users)) (insert "\n") (goto-char (point-max)) (planner-insert-markup (muse-markup-text 'planner-authz-end)) (insert "\n")))))) (defun planner-authz-task-tag (beg end attrs) "Restrict tasks linked to restricted pages. If this page is restricted and the task is linked to another page, remember to republish that page later and restrict the task as it appears there. Call `planner-publish-task-tag' as a side effect." (save-excursion (save-restriction (narrow-to-region beg end) (planner-publish-task-tag beg end attrs) (let* ((link (cdr (assoc "link" attrs))) (linked-pages (if link (mapcar 'planner-link-base (if (featurep 'planner-multi) (planner-multi-split link) link)))) (linked-users (if linked-pages (planner-authz-multi-users linked-pages) (and planner-authz-day-task-default (planner-authz-day-p) (mapconcat 'identity planner-authz-day-task-default " "))))) ;; If this task is linked to another page, republish that page ;; later to restrict the task as it appears there, providing that ;; page has an authz restriction (if linked-pages (planner-authz-republish-dependencies-maybe linked-pages)) ;; If the linked page has an authz restriction, restrict this task (when linked-users (goto-char (point-min)) (planner-insert-markup (muse-markup-text 'planner-authz-begin linked-users)) (goto-char (point-max)) (planner-insert-markup (muse-markup-text 'planner-authz-end))))))) (defun planner-authz-users (&optional page) "Return a list of acceptable users for PAGE. The list of users is returned as space-separated string, based on a #authz directive appearing in the page. If PAGE contains no #authz directive and is a project page (it doesn't match `planner-date-regexp'), return `planner-authz-project-default' as a space-separated string. If PAGE is nil, return a list of users associated with the current page." (unless page (setq page (planner-page-name))) (let ((match (cdr (assoc page planner-authz-pages)))) (unless match (let ((file (cdr (assoc page (planner-file-alist))))) (setq match (or (and file (with-temp-buffer (insert-file-contents-literally file) (if (re-search-forward "^#authz\\s-+\\(.+\\)\n+" nil t) (match-string 1)))) (planner-authz-default page)))) (push `(,page . ,match) planner-authz-pages)) match)) (defun planner-authz-multi-intersection (list) "Merge a list of `planner-authz' access lists, returning a list of only those user names that are common to all the passed access lists." (let ((count (length list)) alist intersection sublist) ;; in alist, associate each name with its frequency of appearance (while list (setq sublist (car list)) (while sublist (let ((entry (assoc (car sublist) alist))) (if entry (setcdr entry (1+ (cdr entry))) (setq alist (cons `(,(car sublist) . 1) alist)))) (setq sublist (cdr sublist))) (setq list (cdr list))) ;; those names with `count' frequencies were in every sublist (while alist (if (= (cdar alist) count) (setq intersection (cons (caar alist) intersection))) (setq alist (cdr alist))) intersection)) (defun planner-authz-multi-union (list) "Merge a list of `planner-authz' access lists, returning a list of all the unique user names in any of those access lists." (let (sublist union) (while list (setq sublist (car list)) (while sublist (add-to-list 'union (car sublist)) (setq sublist (cdr sublist))) (setq list (cdr list))) union)) (defun planner-authz-multi-users (pages) "Return a merged access list for PAGES. The list of users is returned as space-separated string, based on a #authz directive appearing in the PAGES. If one of PAGES contains no #authz directive and is a project page (it doesn't match `planner-date-regexp'), it will contribute `planner-authz-project-default' to the merge." (let ((users (funcall planner-authz-multi-func (mapcar (lambda (page) (if (not (planner-authz-day-p page)) (let ((users (planner-authz-users page))) (if users (split-string users))))) pages)))) (if users (mapconcat 'identity users " ")))) (add-hook 'muse-after-project-publish-hook 'planner-authz-after-project-publish) (let ((styles (list "html" "xhtml"))) (while styles (let ((style (concat "planner-authz-mason-" (car styles)))) (unless (assoc style muse-publishing-styles) (muse-derive-style style (concat "planner-" (car styles)) :before 'planner-authz-before-markup :after 'planner-authz-after-markup :functions 'planner-authz-markup-functions :regexps 'planner-authz-markup-regexps :strings 'planner-authz-mason-markup-strings :tags (append planner-authz-markup-tags planner-publish-markup-tags)))) (setq styles (cdr styles)))) (provide 'planner-authz) ;;; planner-authz.el ends here planner-el/planner-bbdb.el000066400000000000000000000071351226462314700160000ustar00rootroot00000000000000;;; planner-bbdb.el --- BBDB integration for the Emacs Planner ;; Copyright (C) 2001, 2003, 2004, 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2004, 2008 Andrew J. Korty ;; Author: John Wiegley ;; Keywords: planner, gnus ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_ + Commentary: ;; This file allows you to refer to your contacts easily from within ;; a planner page. ;; ;; Example: ;; [[bbdb://Sacha.*Chua][Sacha]] will be linked to the blog, web ;; or net fields of the first matching BBDB record. ;;;_ + Contributors ;; Andrew J. Korty (ajk AT iu DOT edu) had the idea to add the mailto: ;; URI and provided the initial patch for it. ;; ;; Yann Hodique helped to port this to Muse. ;;; Code: (require 'planner) (require 'bbdb-com) (defun planner-bbdb-get-name-from-address (address) "Return the name for ADDRESS to be used in links." (let* ((addr (mail-extract-address-components address)) (rec (apply 'bbdb-search-simple addr))) (if rec (bbdb-record-name rec) (or (car addr) (cadr addr))))) (defvar planner-bbdb-plan-field "plan" "Field that contains a planner page associated with this record.") ;;;###autoload (defun planner-bbdb-annotation-from-bbdb () "If called from a bbdb buffer, return an annotation. Suitable for use in `planner-annotation-functions'." (when (eq major-mode 'bbdb-mode) (or (bbdb-record-getprop (bbdb-current-record) 'plan) ;; From a BBDB entry with a plan page; use that. Yay! (planner-make-link (concat "bbdb://" (planner-replace-regexp-in-string " " "." (bbdb-record-name (bbdb-current-record)))) (bbdb-record-name (bbdb-current-record)))))) ;;;###autoload (defun planner-bbdb-browse-url (url) "If this is a BBDB URL, jump to it." (when (string-match "^bbdb:/?/?\\(.+\\)" url) (bbdb (match-string 1 url) nil) t)) ;;;###autoload (defun planner-bbdb-resolve-url (id) "Replace ID with the blog, web or e-mail address of the BBDB record." (save-match-data (when (string-match "\\`bbdb:/+" id) (setq id (replace-match "" t t id))) (let ((record (car (bbdb-search (bbdb-records) id id id)))) (or (and record (or (bbdb-record-getprop record 'blog) (bbdb-record-getprop record 'web) (when (car (bbdb-record-net record)) (concat "mailto:" (car (bbdb-record-net record)))))) nil)))) (planner-add-protocol "bbdb:/+" 'planner-bbdb-browse-url 'planner-bbdb-resolve-url) (add-hook 'planner-annotation-functions 'planner-bbdb-annotation-from-bbdb) (custom-add-option 'planner-annotation-functions 'planner-bbdb-annotation-from-bbdb) (defalias 'planner-get-name-from-address 'planner-bbdb-get-name-from-address) (provide 'planner-bbdb) ;;; planner-bbdb.el ends here planner-el/planner-bibtex.el000066400000000000000000000110641226462314700163600ustar00rootroot00000000000000;; planner-bibtex.el -- BibTeX support for Planner ;; Copyright (c) 2004, 2008 James Clarke ;; Parts copyright (c) 2004, 2008 Jody Klymak ;; Parts copyright (C) 2005, 2008 Free Software Foundation, Inc. ;; Author: James Clarke ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Provides bibtex annotations for Planner mode. Handles the two ;; versions of bibtex.el I have encountered, those bundled with ;; emacs-21.3 and emacs-21.2. ;;; Contributors: ;; Jody Klymak co-wrote this. ;; Jim Ottaway fixed several bugs. ;; Wei-Hao Lin fixed a typo. (require 'planner) (require 'bibtex) ;; This function is not present in old bibtex.els so I've added it ;; here as I cannot find alternative in old bibtex.els. (defvar planner-bibtex-separator ":" "Character separating filename and label.") (defvar planner-bibtex-regexp (concat "\\`bibtex:\\([^" planner-bibtex-separator "\n]+\\)" planner-bibtex-separator "\\(.+\\)") "Regexp matching URLs.") ;;; Code: (defun planner-bibtex-key-in-head (&optional empty) "Extract BibTeX key in head. Return optional arg EMPTY if key is empty." (if (fboundp 'bibtex-key-in-head) (bibtex-key-in-head empty) (if (match-beginning bibtex-key-in-head) (buffer-substring-no-properties (match-beginning bibtex-key-in-head) (match-end bibtex-key-in-head)) empty))) ;; makes a nice bibtex url with the title upto a terminator for the ;; link name. For emacs 21.3 (updated bibtex.el) ;;;###autoload (defun planner-bibtex-annotation-new () "Return an annotation for the current bibtex entry." (when (planner-derived-mode-p 'bibtex-mode) (save-excursion (let ((titlestring (bibtex-autokey-get-field "title" bibtex-autokey-titleword-change-strings))) (if (string-match "[\.:!\?;]" titlestring) (setq titlestring (substring titlestring 0 (match-beginning 0)))) (bibtex-beginning-of-entry) (re-search-forward bibtex-entry-maybe-empty-head nil t) (planner-make-link (concat "bibtex:" (buffer-file-name) planner-bibtex-separator (planner-bibtex-key-in-head)) titlestring t))))) ;; makes a nice bibtex url with the title up to a terminator for the ;; link name. For emacs 21.2 (older bibtex) ;;;###autoload (defun planner-bibtex-annotation-old () "Return the filename on the current line in dired." (when (planner-derived-mode-p 'bibtex-mode) (save-excursion (let* ((min (bibtex-beginning-of-entry)) (max (bibtex-end-of-entry)) (titlestr (planner-replace-regexp-in-string "[ \t\n]+" " " (bibtex-autokey-get-titlestring min max)))) (bibtex-beginning-of-entry) (re-search-forward bibtex-entry-maybe-empty-head nil t) (planner-make-link (concat "bibtex:" (buffer-file-name) planner-bibtex-separator (planner-bibtex-key-in-head)) titlestr t))))) ;;decide which version of the function to use (if (fboundp 'bibtex-autokey-get-field) (defalias 'planner-bibtex-annotation 'planner-bibtex-annotation-new) (defalias 'planner-bibtex-annotation 'planner-bibtex-annotation-old)) ;;;###autoload (defun planner-bibtex-browse-url (url) "If this is a Bibtex URL, jump to it." (when (string-match planner-bibtex-regexp url) (let ((file (match-string 1 url)) (label (match-string 2 url))) (find-file file) (widen) (goto-char (point-min)) (search-forward (concat "{" label ","))))) (planner-add-protocol "bibtex:" 'planner-bibtex-browse-url nil) (add-hook 'planner-annotation-functions 'planner-bibtex-annotation) (planner-update-wiki-project) (provide 'planner-bibtex) ;;; planner-bibtex.el ends here planner-el/planner-bookmark.el000066400000000000000000000100101226462314700166760ustar00rootroot00000000000000;;; planner-bookmark.el --- bookmark URL support for the Emacs planner ;; ;; Copyright (C) 2004, 2005, 2008 Dryice Dong Liu. All rights reserved. ;; Parts copyright (C) 2005, 2008 Free Software Foundation, Inc. ;; Keywords: emacs planner bookmark remember note ;; Author: Dryice Liu ;; Description: use bookmark.el in Emacs planner ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; Place planner-bookmark.el in your load path and add this to your .emacs: ;; ;; (require 'planner-bookmark) ;; ;; Annotations will be of the form ;; [[bookmark://bookmark-name][bookmark-description]] ;; bookmark-description will use bookmark-annotation if available, ;; else bookmark-name will be used. ;; ;; Note this file advice `bookmark-set'. If you don't want to take a ;; note everytime you set a bookmark, set ;; `planner-bookmark-take-note-after-set-bookmark-flag' to nil ;;; CODE (require 'planner) (require 'bookmark) ;;; User variables ;;; Code: (defgroup planner-bookmark nil "Bookmark URL support for planner.el." :prefix "planner-bookmark" :group 'planner) (defcustom planner-bookmark-take-note-after-set-bookmark-flag t "Non-nil means show a `remember' buffer after setting a new bookmark." :type 'boolean :group 'planner-bookmark) (defcustom planner-bookmark-add-note-title-flag t "Non-nil means add the bookmark name as the default note title" :type 'boolean :group 'planner-bookmark) ;;;; User variables stop here (defadvice bookmark-set (after planner-bookmark activate) "Display a `remember' buffer for the bookmark. This code is run only if `planner-bookmark-take-note-after-set-bookmark-flag' is non-nil." (if (and planner-bookmark-take-note-after-set-bookmark-flag (condition-case nil (require 'remember) ('file-error nil))) ;; bookmark can take us where we want. we don't need two URLs (let ((remember-annotation-functions nil)) (remember (concat (if planner-bookmark-add-note-title-flag bookmark-current-bookmark) "\n\n" (planner-bookmark-make-url bookmark-current-bookmark)))))) ;;;###autoload (defun planner-bookmark-annotation-from-bookmark () "If called from a bookmark buffer, return an annotation. Suitable for use in `planner-annotation-functions'." (if (and (eq major-mode 'bookmark-bmenu-mode) (bookmark-bmenu-check-position)) (planner-bookmark-make-url (bookmark-bmenu-bookmark)))) (defun planner-bookmark-make-url (bookmark-name) "Make the bookmark URL by given BOOKMARK-NAME." (let ((bookmark-annotation (bookmark-get-annotation bookmark-name))) (if (string-equal bookmark-annotation "") (setq bookmark-annotation nil)) (planner-make-link (concat "bookmark://" bookmark-name) (or bookmark-annotation bookmark-name) t))) ;;;###autoload (defun planner-bookmark-browse-url (url) "If this is a bookmark URL, jump to it." (when (string-match "\\`bookmark:/?/?\\(.+\\)" url) (bookmark-jump (match-string 1 url)) t)) (planner-add-protocol "bookmark:/?/?" 'planner-bookmark-browse-url nil) (add-hook 'planner-annotation-functions 'planner-bookmark-annotation-from-bookmark) (custom-add-option 'planner-annotation-functions 'planner-bookmark-annotation-from-bookmark) (provide 'planner-bookmark) ;;; planner-bookmark.el ends here planner-el/planner-calendar.el000066400000000000000000000345501226462314700166610ustar00rootroot00000000000000;;; planner-calendar.el --- Create a clickable calendar in published html ;; Copyright (C) 2003, 2004, 2008 Gary V. Vaughan (gary AT gnu DOT org) ;; Parts copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Filename: planner-calendar.el ;; Version: 1.1 ;; Date: Tue, 1 June 2004 ;; Keywords: hypermedia ;; Author: Gary V. Vaughan (gary AT gnu DOT org) ;; Description: Create a clickable calendar in published html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; You will need to install Emacs Muse before this is of any use to ;; you. ;; To publish calendars in your day pages, it is necessary to do two ;; steps. ;; ;; 1. Add (require 'planner-calendar) to your configuration. ;; ;; 2. Add a tag to either your header, footer, or ;; `planner-day-page-template', depending on where you want it to ;; appear. ;; If you decide to create a today link for published planner pages, ;; add a hook function like this: ;; ;; (eval-after-load "muse-publish" ;; '(add-hook 'muse-after-publish-hook ;; 'planner-calendar-create-today-link)) ;;; Contributors: ;; drkm contributed a small patch that fixes a ;; planner-calendar boundary case when last day of the month is ;; Sunday. ;;; Code: (require 'calendar) (require 'muse) (require 'planner) (eval-when-compile (require 'planner-publish)) (defgroup planner-calendar nil "Options controlling the behaviour of planner calendar publication." :group 'planner) (defcustom planner-calendar-prev-month-button "«" "*Default html entity to use for previous month buttons." :type 'string :group 'planner-calendar) (defcustom planner-calendar-next-month-button "»" "*Default html entity to use for next month buttons." :type 'string :group 'planner-calendar) (defcustom planner-calendar-day-header-chars 3 "*Default number of characters to use for day column header names." :type 'integer :group 'planner-calendar) (defcustom planner-calendar-html-tag-marker "
    " "*Default html block element to add calendar HTML to." :type 'string :group 'planner-calendar) (defcustom planner-calendar-today-page-name "today" "*Default base name for published today page link file." :type 'string :group 'planner-calendar) (defcustom planner-calendar-nop-buttons-flag t "Non-nil means add tags before navigation buttons in the calendar." :type 'boolean :group 'planner-calendar) (defmacro planner-calendar-render (var begin end tag class &rest body) "Generate a row of days for the calendar." `(let (string) (calendar-for-loop ,var from ,begin to ,end do (let ((day (mod (+ calendar-week-start-day i) 7)) (wrap-p (and (= 6 (mod ,var 7)) (/= ,var ,end)))) (setq string (concat string "<" ,tag " class=\"" ,class " " (calendar-day-name day nil t) "\">" ,@body "\n" (and wrap-p "\n\n"))))) string)) (put 'planner-calendar-render 'lisp-indent-function 1) (defun planner-calendar-date-to-filename (date) "See `planner-date-to-filename' except don't choke on nil DATE." (and date (planner-date-to-filename date))) ;; calendar-week-start-day (defun planner-calendar (month year &optional arrows) "Generate a string of html to render a clickable calendar for MONTH YEAR. If ARROWS is non-nil, include prev/next month arrows." (let* ((blank-days ; at start of month (mod (- (calendar-day-of-week (list month 1 year)) calendar-week-start-day) 7)) (last (calendar-last-day-of-month month year)) (pad-days ; at end of month (- 7 (1+ (calendar-day-of-week (list month last year))))) ;; don't use leading whitespace in the generated html, or the ;; other markup rules will add
    sections! (string (concat "\n" "\n" (if arrows (concat "\n" "\n" (when arrows (concat "\n")) "\n" "\n" ;; add day name headings (planner-calendar-render i 0 6 "th" "month-calendar-day-head" (calendar-day-name day planner-calendar-day-header-chars t)) "\n" "\n" ;; add blank days before the first of the month (planner-calendar-render i 0 (1- blank-days) "td" "month-calendar-day-noday" " ") ;; put in the days of the month (planner-calendar-render i blank-days (+ last blank-days -1) "td" (if (planner-page-file (planner-calendar-date-to-filename (list month (- i blank-days -1) year))) "month-calendar-day-link" "month-calendar-day-nolink") (planner-calendar-published-file-href (planner-calendar-date-to-filename (list month (- i blank-days -1) year)) (int-to-string (- i blank-days -1)) planner-calendar-nop-buttons-flag)) ;; add padding days at end of month to make rule lines neat (unless (zerop (mod (+ blank-days last) 7)) (planner-calendar-render i (+ last blank-days) (+ last blank-days pad-days -1) "td" "month-calendar-day-noday" " ")) "\n" "
    " (planner-calendar-prev-month-href month year planner-calendar-prev-month-button planner-calendar-nop-buttons-flag) "\n") "\n") (format "%s %d" (calendar-month-name month) year) "" (planner-calendar-next-month-href month year planner-calendar-next-month-button planner-calendar-nop-buttons-flag) "
    \n"))) string)) (defun planner-calendar-coerce-day-page (&optional page) "Figure out what day page to use, based on PAGE." (save-match-data (unless page (or (and (setq page (planner-page-name)) (stringp page) (string-match planner-date-regexp page)) (setq page (planner-today))))) page) (defun planner-calendar-from-page (&optional arrows page) "Generate a string of html (possibly with ARROWS) for a calendar for PAGE." (setq page (planner-calendar-coerce-day-page page)) (when (and (stringp page) (save-match-data (string-match planner-date-regexp page))) (let ((year (string-to-number (substring page 0 4))) (month (string-to-number (substring page 5 7)))) (planner-calendar month year arrows)))) (defun planner-calendar-published-file-href (page &optional name nop) "Return an href anchor string to the published PAGE if PAGE exists." (if (and (stringp page) (planner-page-file page) (not (planner-private-p (planner-page-file page)))) (planner-link-href page (or name page)) (or name page))) (defun planner-calendar-yesterday (date) "Return the day before DATE as a (month day year) list." (let* ((year (extract-calendar-year date)) (month (extract-calendar-month date)) (day (extract-calendar-day date)) (prev-year (if (and (= 1 month) (= 1 day)) (1- year) year)) (prev-month (if (= 1 day) (1+ (mod (+ month 10) 12)) month)) (prev-day (if (= 1 day) (calendar-last-day-of-month prev-month prev-year) (1- day)))) (list prev-month prev-day prev-year))) (defun planner-calendar-tomorrow (date) "Return the day after DATE as a (month day year) list." (let* ((year (extract-calendar-year date)) (month (extract-calendar-month date)) (day (extract-calendar-day date)) (last-day (calendar-last-day-of-month month year)) (next-year (if (and (= 12 month) (= 31 day)) (1+ year) year)) (next-month (if (>= day last-day) (1+ (mod month 12)) month)) (next-day (if (< day last-day) (1+ day) 1))) (list next-month next-day next-year))) (defun planner-calendar-today (&optional max-days) "Return today or the first day before today with a day page." (planner-calendar-prev-date (planner-calendar-tomorrow (calendar-current-date)))) (defun planner-calendar-create-today-link (&optional name) "Create a link to the newest published day page. Add this to `muse-after-publish-hook' to create a \"today\" soft link to the newest published planner day page, on operating systems that support POSIX \"ln\"." (let* ((today-name planner-calendar-today-page-name) (target-file (planner-published-file (or name today-name))) (source-file (planner-published-file (planner-calendar-date-to-filename (planner-calendar-today))))) (when (and (stringp target-file) (stringp source-file) (file-exists-p source-file)) (when (file-exists-p target-file) (funcall planner-delete-file-function target-file)) (make-symbolic-link source-file target-file t)))) (defun planner-calendar-prev-date (date &optional max-days) "Return the first day before DATE with a day page." (let ((days (or max-days 180)) (yesterday date) (done nil)) (while (and (not done) (> days 0)) (setq yesterday (planner-calendar-yesterday yesterday) days (1- days)) (let ((page (planner-calendar-date-to-filename yesterday))) (setq done (and (planner-page-file page) (not (planner-private-p (planner-page-file page))))))) (if done yesterday nil))) (defun planner-calendar-next-date (date &optional max-days) "Return the first day after DATE with a day page." (let ((days (or max-days 180)) (tomorrow date) (done nil)) (while (and (not done) (> days 0)) (setq tomorrow (planner-calendar-tomorrow tomorrow) days (1- days)) (let ((page (planner-calendar-date-to-filename tomorrow))) (setq done (and (planner-page-file page) (not (planner-private-p (planner-page-file page))))))) (if done tomorrow nil))) (defun planner-calendar-prev-date-href (date name &optional nop max-days) "Return an href anchor string for the first day page before DATE." (let ((prev-date (planner-calendar-prev-date date max-days))) (planner-calendar-published-file-href (planner-calendar-date-to-filename prev-date) name nop))) (defun planner-calendar-next-date-href (date name &optional nop max-days) "Return an href anchor string for the first day page after DATE." (let ((next-date (planner-calendar-next-date date max-days))) (planner-calendar-published-file-href (planner-calendar-date-to-filename next-date) name nop))) (defun planner-calendar-prev-month-href (month year name &optional nop max-days) "Return an href anchor string for the last day page in the previous month." (let ((prev-date (planner-calendar-prev-date (list month 1 year) max-days)) (muse-publish-desc-transforms nil) (planner-publish-ignore-url-desc-specials t)) (planner-calendar-published-file-href (planner-calendar-date-to-filename prev-date) name nop))) (defun planner-calendar-next-month-href (month year name &optional nop max-days) "Return an href anchor string for the first day page in the following month." (let ((next-date (planner-calendar-next-date (list month (calendar-last-day-of-month month year) year) max-days)) (muse-publish-desc-transforms nil) (planner-publish-ignore-url-desc-specials t)) (planner-calendar-published-file-href (planner-calendar-date-to-filename next-date) name nop))) (defun planner-calendar-prev-day-page (&optional page max-days) "Return the first planner day page before this one." (unless page (setq page (planner-page-name))) (let ((date (planner-filename-to-calendar-date page))) (planner-calendar-date-to-filename (planner-calendar-prev-date date max-days)))) (defun planner-calendar-next-day-page (&optional page max-days) "Return the first planner day page after this one." (unless page (setq page (planner-page-name))) (let ((date (planner-filename-to-calendar-date page))) (planner-calendar-date-to-filename (planner-calendar-next-date date max-days)))) (defun planner-calendar-prev-date-href-from-page (name &optional page max-days) "Return an href anchor string for the first day page before this one." (unless page (setq page (planner-page-name))) (let ((date (planner-filename-to-calendar-date page))) (planner-calendar-prev-date-href date name max-days))) (defun planner-calendar-next-date-href-from-page (name &optional page max-days) "Return an href anchor string for the first day page after this one." (unless page (setq page (planner-page-name))) (let ((date (planner-filename-to-calendar-date page))) (planner-calendar-next-date-href date name max-days))) (defun planner-calendar-prev-month-href-from-page (name &optional page max-days) "Return a string for the last day page in first month before this one." (unless page (setq page (planner-page-name))) (let ((date (planner-filename-to-calendar-date page))) (planner-calendar-prev-month-href date name max-days))) (defun planner-calendar-next-month-href-from-page (name &optional page max-days) "Return a string for the first day page in the first month after this one." (unless page (setq page (planner-page-name))) (let ((date (planner-filename-to-calendar-date page))) (planner-calendar-next-month-href date name max-days))) (defun planner-publish-calendar-tag (beg end attrs) (let* ((arrows (cdr (assoc "arrows" attrs))) (page (cdr (assoc "page" attrs))) (calendar (planner-calendar-from-page arrows page))) (delete-region beg end) (when calendar (planner-insert-markup "
    \n") (planner-insert-markup calendar) (planner-insert-markup "
    \n")))) (eval-after-load "planner-publish" '(progn (add-to-list 'planner-publish-markup-tags '("calendar" nil t nil planner-publish-calendar-tag) t) (add-to-list 'planner-publish-finalize-regexps '(200 "<\\(calendar\\)\\(\\s-+[^<>\n]+[^\n]\\)?\\(/\\)?>" 0 muse-publish-markup-tag)))) (provide 'planner-calendar) ;;; planner-calendar.el ends here ;; ;; Local Variables: ;; indent-tabs-mode: t ;; tab-width: 8 ;; End: planner-el/planner-cyclic.el000066400000000000000000000116121226462314700163500ustar00rootroot00000000000000;;; planner-cyclic.el --- Cyclic task support for the Emacs Planner ;; Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Sergey Vlasov (vsu AT altlinux.ru) ;; Filename: planner-cyclic.el ;; Author: Sacha Chua ;; Description: Provide cyclic task support ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; Place planner-cyclic.el in your load path and add this to your .emacs: ;; ;; (require 'planner-cyclic) ;; ;; Create a diary file named ~/.diary.cyclic-tasks ;; (or the value of planner-cyclic-diary-file). Example: ;; ;; Tuesday #B0 _ Study Japanese ;; Friday #B0 _ Study Japanese (JapaneseStudies) ;; ;; The first will be a plain task, the second will be linked. ;; ;; By default, planner-cyclic creates multiple tasks if you let tasks build up ;; (that is, the next Tuesday rolls around and you _still_ haven't ;; marked the task as done.) To turn off this behavior: ;; ;; (setq planner-cyclic-diary-nag nil) ;;; Code: (require 'planner) (require 'diary-lib) (defcustom planner-cyclic-diary-file "~/.diary.cyclic-tasks" "Diary file containing cyclic tasks." :type 'string :group 'planner) (defcustom planner-cyclic-diary-nag t "If non-nil, create tasks even if there are procrastinated cyclic tasks." :type 'boolean :group 'planner) (defcustom planner-cyclic-task-description-format "%s from %s" "Format used by `planner-cyclic-generate-task' when creating a task. This string must be a valid control string for `format'. First format argument is the task description read from `planner-cyclic-diary-file', second argument is the date string. If this format is changed when you already have some cyclic tasks created with the old format, `planner-cyclic-create-tasks-maybe' will add the same tasks with the new format, unless you convert existing tasks to the new format manually." :type 'string :group 'planner) ;;; functions (defun planner-cyclic-get-cyclic-tasks (date &optional no-of-days) "For DATE, get the cyclic tasks." (let ((date (if (stringp date) (planner-filename-to-calendar-date date) date))) (delq nil (mapcar (lambda (item) (when (string-match "#[A-C].+" (elt item 1)) (match-string 0 (elt item 1)))) (planner-list-diary-entries planner-cyclic-diary-file date 1))))) (defun planner-cyclic-generate-task (date task-string) "For DATE, generate a cyclic task based on TASK-STRING." (let ((info (planner-task-info-from-string date task-string))) (if info (setcar (nthcdr 4 info) (format planner-cyclic-task-description-format (planner-task-description info) date)) (message "Cannot parse task %s" task-string)) info)) (defun planner-cyclic-create-task-maybe (date task-string) "For DATE, possibly create a task based on TASK-STRING." (when (string-match planner-task-regexp task-string) (let ((orig-task (planner-task-info-from-string date task-string)) (new-task (planner-cyclic-generate-task date task-string))) (unless (planner-find-task new-task) (when (or planner-cyclic-diary-nag (not (planner-find-task orig-task))) (planner-create-task-from-info new-task nil nil nil nil nil date)))))) ;;;###autoload (defun planner-cyclic-create-tasks-maybe () "Maybe create cyclic tasks. This will only create tasks for future dates or today." (interactive) (when (and (planner-derived-mode-p 'planner-mode) (planner-page-name) (not muse-publishing-p) (string-match planner-date-regexp (planner-page-name)) (or (string< (planner-today) (planner-page-name)) (string= (planner-today) (planner-page-name)))) (mapcar (lambda (task-string) (when task-string (planner-cyclic-create-task-maybe (planner-page-name) task-string))) (planner-cyclic-get-cyclic-tasks (planner-page-name))))) (add-hook 'planner-mode-hook 'planner-cyclic-create-tasks-maybe) (provide 'planner-cyclic) ;;; planner-cyclic.el ends here planner-el/planner-deadline.el000066400000000000000000000156571226462314700166640ustar00rootroot00000000000000;;; planner-deadline.el --- Deadlines for planner.el ;; Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2004, 2005, 2008 Dryice Dong Liu ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center ;; Author: Sandra Jean Chua (Sacha) ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; With the default setup, make your tasks of the form ;; ;; #A0 _ Some task {{Deadline: 2004.09.12}} ;; ;; Note: There must be at least one space after the colon. ;; ;; Run M-x planner-deadline-update to update the task descriptions. (require 'planner) ;;; Code: ;;; USER VARIABLES ----------------------------------------------------------- (defgroup planner-deadline nil "Deadline reports for planner.el." :prefix "planner-deadline" :group 'planner) (defcustom planner-deadline-change-hook '(planner-deadline-update) "Functions to run after `planner-deadline-change'. Point will be on the same line as the task." :type 'hook :options '(planner-deadline-update) :group 'planner-deadline) (defcustom planner-deadline-regexp "\\({{Deadline:\\s-+\\([0-9]+[\\.\\-][0-9]+[\\.\\-][0-9]+\\)[^}]*}}\\)" "Regular expression for deadline data. The special deadline string should be regexp group 1. The date (YYYY.MM.DD) should be regexp group 2." :type 'regexp :group 'planner-deadline) (defun planner-deadline-get-deadline-from-string (string) "Return the deadline in STRING." (save-match-data (if (string-match planner-deadline-regexp string) (planner-match-string-no-properties 2 string) nil))) (defun planner-deadline-get-current-deadline () "Return the deadline of the current task." (planner-deadline-get-deadline-from-string (buffer-substring (planner-line-beginning-position) (planner-line-end-position)))) (defun planner-deadline-days-left (deadline date) "Return how many days are left for DEADLINE with effective DATE." (let (diff (date (if (listp date) (planner-task-date date) date))) (if date (setq diff (- (calendar-absolute-from-gregorian (planner-filename-to-calendar-date deadline)) (calendar-absolute-from-gregorian (planner-filename-to-calendar-date date)))) (setq date (if (not planner-use-day-pages) (planner-date-to-filename (decode-time (current-time))) (if (string-match planner-date-regexp (planner-page-name)) (planner-page-name) (planner-today))))) (setq diff (- (calendar-absolute-from-gregorian (planner-filename-to-calendar-date deadline)) (calendar-absolute-from-gregorian (planner-filename-to-calendar-date date)))) diff)) (defun planner-deadline-calculate-string (deadline &optional date) "Return a deadline string for DEADLINE and effective DATE." (let ((diff (planner-deadline-days-left deadline date))) (concat "{{Deadline: " deadline " - " (cond ((< diff 0) (format "%d %s *OVERDUE*" (- diff) (if (= diff -1) "day" "days"))) ((= diff 0) "*TODAY*") (t (format "%d %s" diff (if (= diff 1) "day" "days")))) "}}"))) ;;;###autoload (defun planner-deadline-update () "Replace the text for all tasks with deadlines. By default, deadlines are of the form {{Deadline: yyyy.mm.dd}}. See `planner-deadline-regexp' for details." (interactive) (with-planner-update-setup (goto-char (point-min)) (while (re-search-forward planner-deadline-regexp nil t) (let* ((deadline (match-string 2)) (task-info (save-match-data (planner-current-task-info))) (status (planner-task-status task-info)) (end (match-end 0)) new) (save-match-data (if task-info (unless (or (equal status "X") (equal status "C")) (setq new (planner-deadline-calculate-string deadline task-info))) (setq new (planner-deadline-calculate-string deadline nil)))) (when new (if task-info (when (string-match planner-deadline-regexp (planner-task-description task-info)) (planner-edit-task-description (replace-match new t t (planner-task-description task-info)))) (replace-match new t t) (when (planner-current-note-info) (planner-update-note)))) (goto-char (1+ end)))))) ;;;###autoload (defun planner-deadline-change (date) "Change the deadline of current task to DATE. If DATE is nil, prompt for it." (interactive (list (planner-read-date nil t))) (let* ((info (planner-current-task-info)) (description (planner-task-description info))) (when date (when (string-match (concat "\\s-*" planner-deadline-regexp) description) (setq description (replace-match "" t t description))) (planner-edit-task-description (concat description " {{Deadline: " date "}}")) (run-hooks 'planner-deadline-change-hook)))) ;;;###autoload (defalias 'planner-deadline-add 'planner-deadline-change) ;;;###autoload (defun planner-deadline-remove () "Remove the deadline of the current task." (interactive) (let* ((info (planner-current-task-info)) (description (planner-task-description info))) (when (string-match (concat "\\s-*" planner-deadline-regexp) description) (setq description (replace-match "" t t description)) (planner-edit-task-description description)))) ;; Insinuate planner-deadline-update into planner-goto-hook (add-to-list 'planner-goto-hook 'planner-deadline-update) (provide 'planner-deadline) ;;; planner-deadline.el ends here planner-el/planner-diary.el000066400000000000000000001116341226462314700162170ustar00rootroot00000000000000;;; planner-diary.el --- Diary integration for the Emacs Planner (planner.el) ;; Copyright (C) 2003, 2004, 2008 Thomas Gehrlein ;; Parts copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Jody Klymak ;; Emacs Lisp Archive Entry ;; Filename: planner-diary.el ;; Time-stamp: "2004-03-27 16:51:20 Thomas Gehrlein" ;; Version: 1.0-devel ;; Keywords: hypermedia ;; Author: Thomas Gehrlein ;; Maintainer: Thomas Gehrlein ;; Description: Integrate the Emacs Planner with Calendar and Diary ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; PLANNER-DIARY ;; The following documentation describes the stable version of ;; planner-diary (v1.0). If planner-diary doesn't do what I claim ;; here, then it's a bug and you will fix it. This file contains ;; additional code that is part of the development version of planner. ;; This code may or may not work. Use it at your own risk. ;; ;;; Commentary: ;; ;; If you use Emacs' diary feature, planner-diary could be helpful for ;; you. It puts all diary entries for the current day in the "* ;; Diary" section of your day plan page. This section is updated ;; every time you display the file in Emacs. By default the diary ;; section of past pages is not updated (it's pretty unlikely that you ;; want to add new diary entries for the past). ;; ;; If you want to use planner-diary.el, put the file in your load path and add ;; this to your .emacs: ;; ;; (require 'planner-diary) ;; ;; (This step should not be necessary once a stable planner package will be put ;; together.) ;; ;; planner-diary.el needs fancy-diary-display. To use fancy-diary-display add ;; this to your .emacs: ;; ;; (add-hook 'diary-display-hook 'fancy-diary-display) ;; ;; You can use planner diary in two different ways: ;; ;; 1) If you want the saved files to contain your entries and not just a line ;; of lisp, add the following lines to your .emacs: ;; ;; (setq planner-diary-use-diary t) ;; (planner-diary-insinuate) ;; ;; You should also customize or set planner-day-page-template to include a ;; "* Diary": ;; ;; (setq planner-day-page-template ;; "* Tasks\n\n\n* Schedule\n\n\n* Diary\n\n\n* Notes") ;; ;; C-c C-e updates the diary sections. C-u C-c C-e forces an update, it ;; inserts the diary section for the day, even if the day is in the past or ;; if there is no Diary section in the buffer. ;; ;; 2) (GNU EMACS ONLY) You can put the following line of lisp code in ;; your day plan pages to display your diary entries: ;; ;; (planner-diary-entries-here) ;; ;; You can do this automatically for all day plan pages: ;; ;; (setq planner-day-page-template ;; "* Tasks\n\n\n* Diary\n\n(planner-diary-entries-here)\n\n* Notes") ;; ;; When you open a day plan page outside emacs, you will see the ;; line of lisp code and not your diary entries. ;; ;; If you want to see your diary entries for more than just 1 day, set ;; `planner-diary-number-of-diary-entries' accordingly. This works for ;; either of the 2 approaches. ;; ;; If you want to use the cal-desk package, simply follow the ;; instructions in cal-desk.el. If you get the cal-desk layout from ;; the Calendar buffer, you get it in the day plan buffer, too. ;; ;; If you use planner-diary, you might consider using the Calendar ;; support of planner. To get Calendar integration add this to your ;; .emacs: ;; ;; (planner-insinuate-calendar) ;; ;; For further information refer to the documentation for this function. ;; ;; If you have questions about planner-diary, feature requests, bug reports or ;; anything else you want to tell me: thomas.gehrlein@t-online.de. ;;; HISTORY: ;; version 1.0 First stable version. Expected to work as documented. Same ;; feature of previous versions are not supported. ;; ;; version 0.7 Major rewrite. New diary types (cal-desk, appointments, privat, ;; public diaries). Add diary entries from planner pages. ;; ;; version 0.6 minor changes ;; ;; version 0.5 appointment integration (thanks to Bastien Guerry) ;;; ADVANCED FEATURES ;; (The features described here are part of the development version. They are ;; subject to change without notice. They may be buggy. The documentation may ;; be inaccurate. Use at your own risk.) ;; There is a lot of code redundancy in the development version. This is ;; intentional and makes it easier to change the code for one type of diary ;; section without breaking others. ;; Currently planner-diary supports 6 different views of your diary entries: ;; 1) Ordinary fancy diary display (what you get by pressing d in the calendar ;; buffer with fancy-diary-display switched on) ;; 2) Schedule/Appointments (all entries from 1 that have a time assigned to ;; them. ;; 3) Diary without appts (1 without 2). ;; 4) cal-desk display (appts on top, non appts entries at bottom) ;; 5) A private diary (same as 1, but uses a different diary-file) ;; 6) A public diary (same as 1, but uses a different diary-file) ;; 1) Put the following line of lisp code in you day plan pages to display your ;; diary entries: ;; ;; (planner-diary-entries-here) ;; ;; The function `planner-diary-entries-here' takes two optional args: The ;; diary file you want to use and the number of days you want to display. ;; ;;; RANDOM THOUGHTS ABOUT PLANNER, CALENDAR, AND DIARY ;; This is planner-diary, not planner-calendar! Include only stuff that has to ;; do with diary and planner, leave the calendar stuff to ;; planner-insinuate-calendar. ;; Deal with holidays. ;; There are 3 ways to use planner with calendar and diary: ;; 1) Use calendar for browsing the day plan pages. ;; Cool features: all days with day plan pages are marked. ">" and "<" move to ;; the next or previous page. (Ordinary diary entries should not be marked.) ;; Entry point: a command (planner-browse-calendar ??) What about key-bindings ;; for "n" and "N"? ;; 2) Display the day plan pages when you move in calendar. ;; Add a hook to calendar-move-hook. Add key-bindings for "n" and "N". ;; 3) Automatically update the diary section in day plan pages. ;; Add a function to planner-goto-hook. This work independent of the first 2. ;;;_ + Contributors ;; Jody Klymak (jklymak AT coas DOT oregonstate DOT edu) added some ;; documentation. ;; Sacha Chua (sacha AT free DOT net DOT ph) provided thoughts and ;; ideas. ;; Bastien Guerry provided a bug report and appointment integration. ;; Travis B. Hartwell (nafai AT travishartwell DOT net) helped fix ;; calendar desk entries and fixed a typo or two. (require 'planner) (require 'diary-lib) (require 'calendar) (require 'cl) ;;; Code: (defgroup planner-diary nil "Diary integration for planner.el." :prefix "planner-diary-" :group 'planner) ;;; USER VARIABLES ;; STANDARD DIARY SUPPORT (no fancy extras - this is what I, the author of ;: this file, use) (defcustom planner-diary-string "* Diary" "*Header for the diary section in a day plan page." :type 'string :group 'planner-diary) (defcustom planner-diary-create-section-flag t "Non-nil means create diary section in future or present day pages." :type 'boolean :group 'planner-diary) (defcustom planner-diary-file diary-file ;; FIXME: Test if this works as buffer-local var "*The diary file you want to use with planner-diary." :type 'file :group 'planner-diary) (defcustom planner-diary-use-diary nil ;; (if (string-match planner-diary-string planner-day-page-template) ;; t ;; nil) "*Non-nil means: Automatically insert a diary section into day plan pages. Uses the standard fancy-diary display." :type 'boolean :group 'planner-diary) (defcustom planner-diary-number-of-days 1 "*Number of days of diary entries displayed in the standard diary section." :type 'number :group 'planner-diary) (defcustom planner-diary-include-all-output-flag nil "Non-nil means don't omit any data when copying diary entries into day pages." :type 'boolean :group 'planner-diary) ;; for backward compatability ;; (defcustom planner-diary-number-of-diary-entries 1 ;; "*Obsolete, use `planner-diary-number-of-days' instead." ;; :type 'number ;; :group 'planner-diary) ;; CAL-DESK (defcustom planner-diary-cal-desk-string "* Cal-Desk" "Header for the cal-desk section in a day plan page. You might want to use \"* Diary\" or \"* Schedule\"." :type 'string :group 'planner-diary) (defcustom planner-diary-cal-desk-file planner-diary-file "The diary file you want to use for your cal-desk section." :type 'file :group 'planner-diary) (defcustom planner-diary-use-cal-desk nil ;; (if (string-match planner-diary-cal-desk-string planner-day-page-template) ;; t ;; nil) "Non-nil means include a cal-desk section in day pages. This section contains only entries from `planner-diary-cal-desk-file'." :type 'boolean :group 'planner-diary) (defcustom planner-diary-cal-desk-number-of-days 1 ; 1 is good for cal-desk's format. "Number of days of diary entries displayed in the cal-desk diary section." :type 'number :group 'planner-diary) ;; DIARY APPOINTMENTS (idea and most of this code from Bastien Guerry) (defcustom planner-diary-appts-string "* Diary Appointments" "*Header for the diary appointments section in a day plan page." :type 'string :group 'planner-diary) (defcustom planner-diary-appts-file planner-diary-file "*The diary file you want to use for your diary appointments section." :type 'file :group 'planner-diary) (defcustom planner-diary-use-appts nil ;; (if (string-match planner-diary-appts-string planner-day-page-template) ;; t ;; nil) "*Non-nil means: Insert a diary appointments section into day plan pages. This displays all diary entries `planner-diary-appts-file' with a time assigned to them." :type 'boolean :group 'planner-diary) (defcustom planner-diary-appts-number-of-days 1 ; 1 is good for appts "Number of days of diary entries displayed in the appointments diary section." :type 'number :group 'planner-diary) (defcustom planner-diary-exclude-appts-from-diary planner-diary-use-appts ; if you use appts, you want to exclude ; them from the diary section "Non-nil means that appts are not shown in the diary section. This is useful if you use a diary appointments section. Diary entries with a time assigned to them will then only be displayed in the diary appointments section and not in the diary section." :type 'boolean :group 'planner-diary) ;; PRIVATE DIARY (defcustom planner-diary-private-string "* Private Diary" "Header for the private diary section in a day plan page. This is the section you don't want to publish. planner-diary doesn't do anything about the publishing, it's up to you to make sure this section doesn't get published." :type 'string :group 'planner-diary) (defcustom planner-diary-private-file planner-diary-file ;; FIXME: Test if this works as buffer-local var "The diary file you want to use with for your private diary." :type 'file :group 'planner-diary) (defcustom planner-diary-use-private-diary nil ;; (if (string-match planner-diary-private-string planner-day-page-template) ;; t ;; nil) "Non-nil means: Insert a private diary section into day plan pages. This section contains only entries from `planner-diary-private-file'." :type 'boolean :group 'planner-diary) (defcustom planner-diary-private-number-of-days planner-diary-number-of-days "Number of days of diary entries displayed in the private diary section." :type 'number :group 'planner-diary) ;; PUBLIC DIARY (defcustom planner-diary-public-string "* Public Diary" "Header for the public diary section in a day plan page. This is the section you want to publish. Obviously, this only makes sense if you have a Private Diary section, too. planner-diary doesn't do anything about the publishing, it's up to you to make sure this section gets published." :type 'string :group 'planner-diary) (defcustom planner-diary-public-file diary-file "The diary file you want to use with for your public diary." :type 'file :group 'planner-diary) (defcustom planner-diary-use-public-diary nil ;; (if (string-match planner-diary-public-string planner-day-page-template) ;; t ;; nil) "Non-nil means: Insert a public diary section into day plan pages. This section contains only entries from `planner-diary-public-file'." :type 'boolean :group 'planner-diary) (defcustom planner-diary-public-number-of-days planner-diary-number-of-days "Number of days of diary entries displayed in the public diary section." :type 'number :group 'planner-diary) ;;; INTERNAL VARS ;; FIXME: Is this used for anything? (defcustom planner-diary-exclude-regexp "" "Regexp for diary entries not displayed in the diary section. Used by the schedule code." :type 'regexp :group 'planner-diary) (defcustom planner-diary-time-regexp "[0-2][0-9]:[0-5][0-9]" ;; FIXME: Internationalize? (AM and PM) "A regexp for time in a diary appt entry." :type 'regexp :group 'planner-diary) ;;; FUNCTIONS ;; GETTING THE RELEVANT ENTRIES ;; planner-diary-get-diary-entries is the main function, ;; planner-diary-get-appts-entries needs to be rewritten. ;; planner-diary-get-[public/private/cal-desk]-entries call ;; planner-diary-get-diary-entries. (defun planner-diary-get-diary-entries (date &optional no-of-days file use-cal-desk) "Get the diary entries for DATE and the following NO-OF-DAYS days from FILE. DATE is a list (month day year). NO-OF-DAYS defaults to `planner-diary-number-of-days'. FILE defaults to `planner-diary-file'. Optional argument USE-CAL-DESK means display using a fancy desk calendar." (save-window-excursion (let* ((fancy-diary-buffer "temporary-fancy-diary-buffer") (entries) (font-lock-defaults nil) (font-lock-mode nil) (diary-display-hook (if use-cal-desk '(sort-diary-entries fancy-diary-display fancy-schedule-display-desk-calendar) '(sort-diary-entries fancy-diary-display))) (no-of-days (or no-of-days planner-diary-number-of-days)) (diary-file (or file planner-diary-file))) (if (fboundp 'diary-list-entries) (diary-list-entries date no-of-days) (list-diary-entries date no-of-days)) (switch-to-buffer fancy-diary-buffer) (let ((inhibit-read-only t)) ;; return "No entries" if buffer is empty (setq entries (if (= (point-max) 1) "No entries" (buffer-substring (if (> no-of-days 1) ; if more than 1 day, show everything (progn (while (re-search-forward "^=+$" nil t) (replace-match (make-string (length (match-string 0)) ?-))) (point-min)) (if planner-diary-include-all-output-flag ;; remove date and lots of =s if just for 1 day (point-min) (goto-char (point-min)) (search-forward-regexp "^=+$") ; one or more = (1+ (point)))) ;; remove final newline (progn (goto-char (point-max)) (when (bolp) (backward-char 1)) (point))))) (kill-buffer fancy-diary-buffer) entries)))) (defun planner-diary-get-cal-desk-entries (date &optional no-of-days file) "Get the cal-desk style diary entries for DATE. Consider the following NO-OF-DAYS days from FILE. DATE is a list (month day year). NO-OF-DAYS defaults to `planner-diary-cal-desk-number-of-days'. FILE defaults to `planner-diary-cal-desk-file'." (planner-diary-get-diary-entries date (or no-of-days planner-diary-cal-desk-number-of-days) (or file planner-diary-cal-desk-file) t)) ;;; TODO: Merge the following two functions into one: (defun planner-diary-get-appts-entries (date &optional no-of-days file) ;; FIXME: use optional args "Call `planner-diary-get-entries' for appointments on DATE. Arguments NO-OF-DAYS and FILE are ignored." (planner-diary-get-entries date 'appt)) (defun planner-diary-get-entries (date &optional type) "Get the appointment diary entries for DATE and the following days. DATE is a list (month day year). Optional arg TYPE ..." ; FIXME: doc for type (save-window-excursion (let* ((regexp planner-diary-exclude-regexp) (no-of-days planner-diary-number-of-days) (init-entries (flet ((message (&rest args) (ignore args))) (if (fboundp 'diary-list-entries) (diary-list-entries date (if type 1 no-of-days)) (list-diary-entries date (if type 1 no-of-days))))) (end-entries (mapcar '(lambda (seq) (let ((seq2 (if (and (eq type 'appt) (string-match planner-diary-time-regexp (cadr seq))) (planner-diary-appt-to-planner (cadr seq)) (cadr seq)))) (unless ; first check no excluded regexp (or (and (not (equal regexp "")) (string-match regexp seq2)) ; then check appt not already there (string-match (substring seq2 0 (1- (length seq2))) ; bug in planner.el ? a space is added ; from diary entries to .diary.planner (buffer-string)) (if (eq type 'appt) (not (string-match planner-diary-time-regexp seq2)) (and (eq type nil) planner-diary-exclude-appts-from-diary (string-match planner-diary-time-regexp (cadr seq))))) seq2))) init-entries))) (mapconcat 'eval (delete-duplicates (remove nil end-entries) :test 'equal) "\n")))) (defun planner-diary-appt-to-planner (appt) "Convert APPT from diary format to planner format." (string-match "\\([0-9]+:[0-9]+[ap]?m?\\)[ ]+\\(.*\\)" appt) (let ((time (match-string 1 appt)) (task (match-string 2 appt))) (concat time " | " task))) (defun planner-diary-get-private-entries (date &optional no-of-days file) "Get private diary entries for DATE and the next NO-OF-DAYS from FILE. DATE is a list (month day year). NO-OF-DAYS defaults to `planner-diary-private-number-of-days'. FILE defaults to `planner-diary-private-file'." (planner-diary-get-diary-entries date (or no-of-days planner-diary-private-number-of-days) (or file planner-diary-private-file))) (defun planner-diary-get-public-entries (date &optional no-of-days file) "Get public diary entries for DATE and the next NO-OF-DAYS days from FILE. DATE is a list (month day year). NO-OF-DAYS defaults to `planner-diary-public-number-of-days'. FILE defaults to `planner-diary-public-file'." (planner-diary-get-diary-entries date (or no-of-days planner-diary-public-number-of-days) (or file planner-diary-public-file))) (defun planner-diary-get-name () "Return current filename." (planner-page-name)) ;;; LISP FUNCTIONS FOR USE IN PLANNER DAY PAGES ;;; arg FILE to specify a diary-file (suggested by David O'Toole) (defun planner-diary-entries-here (&optional file no-of-days) "Display the diary entries from FILE for the next NO-OF-DAYS days. FILE defaults to `planner-diary-file', NO-OF-DAYS defaults to `planner-diary-number-of-days'. Put this is your day pages: \"(planner-diary-entries-here)\" or this, if you want to do fancy things: \"(planner-diary-entries-here \"/path/to/diary/file\" 1)\" You might want to use `planner-day-page-template' to do so." (planner-diary-get-diary-entries (planner-filename-to-calendar-date (planner-diary-get-name)) (or no-of-days planner-diary-number-of-days) (or file planner-diary-file))) (defun planner-diary-appts-entries-here (&optional file no-of-days) "Display the diary appointments entries from FILE for the next NO-OF-DAYS. FILE defaults to `planner-diary-appts-file', NO-OF-DAYS defaults to `planner-diary-appts-number-of-days'. Put this is your day pages: \"(planner-diary-appts-entries-here)\" or this, if you want to do fancy things: \"(planner-diary-appts-entries-here \"/path/to/diary/file\" 1)\" You might want to use `planner-day-page-template' to do so." (planner-diary-get-appts-entries (planner-filename-to-calendar-date (planner-diary-get-name)) (or file planner-diary-appts-file) (or no-of-days planner-diary-appts-number-of-days))) (defun planner-diary-cal-desk-entries-here (&optional file no-of-days) "Display the diary appointments entries from FILE for the next NO-OF-DAYS. FILE defaults to `planner-diary-cal-desk-file', NO-OF-DAYS defaults to `planner-diary-cal-desk-number-of-days'. Put this is your day pages: \"(planner-diary-cal-desk-entries-here)\" or this, if you want to do fancy things: \"(planner-diary-cal-desk-entries-here \"/path/to/diary/file\" 1)\" You might want to use `planner-day-page-template' to do so." (planner-diary-get-cal-desk-entries (planner-filename-to-calendar-date (planner-diary-get-name)) (or file planner-diary-cal-desk-file) (or no-of-days planner-diary-cal-desk-number-of-days))) (defun planner-diary-public-entries-here (&optional file no-of-days) "Display the diary appointments entries from FILE for the next NO-OF-DAYS. FILE defaults to `planner-diary-public-file', NO-OF-DAYS defaults to `planner-diary-public-number-of-days'. Put this is your day pages: \"(planner-diary-public-entries-here)\" or this, if you want to do fancy things: \"(planner-diary-public-entries-here \"/path/to/diary/file\" 1)\" You might want to use `planner-day-page-template' to do so." (planner-diary-get-public-entries (planner-filename-to-calendar-date (planner-diary-get-name)) (or file planner-diary-public-file) (or no-of-days planner-diary-public-number-of-days))) (defun planner-diary-private-entries-here (&optional file no-of-days) "Display the diary appointments entries from FILE for the next NO-OF-DAYS. FILE defaults to `planner-diary-private-file', NO-OF-DAYS defaults to `planner-diary-private-number-of-days'. Put this is your day pages: \"(planner-diary-private-entries-here)\" or this, if you want to do fancy things: \"(planner-diary-private-entries-here \"/path/to/diary/file\" 1)\" You might want to use `planner-day-page-template' to do so." (planner-diary-get-private-entries (planner-filename-to-calendar-date (planner-diary-get-name)) (or file planner-diary-private-file) (or no-of-days planner-diary-private-number-of-days))) ;;; CODE FOR DEALING WITH SECTIONS ;; There's a lot of code duplication in the following 3 functions. ;;;###autoload (defun planner-diary-update-section (file title text &optional force) ;;FIXME: Find a good place to insert a new section "Update FILE's existing section TITLE by replacing existing text with TEXT. If optional arg FORCE is non-nil, update the section even if it doesn't exist, i.e. insert TITLE followed by TEXT at the top of the buffer." ;; search for something like "^* Diary$", delete buffer content to the next ;; "^* " ;; sanity checks (unless (equal major-mode 'planner-mode) (error "This is not a planner buffer")) (save-excursion (goto-char (point-min)) (or (re-search-forward (concat "^" title "$") (point-max) t) (when (or force planner-diary-create-section-flag) (insert title "\n\n\n") (backward-char 3) t) (error "No \"%s\" section in this buffer" title)) ;; point is at the end of something like "* Diary" ;; delete the old text (let ((beg (point)) (end (if (re-search-forward "^* " (point-max) t) (progn (beginning-of-line) (backward-char 1) (point)) (point-max)))) (delete-region beg end) ;; point is at the end of "* Diary" (insert "\n\n") (unless (string= text "") (insert text "\n"))))) (defun planner-diary-insert-diary (&optional force) "Insert the fancy diary for the day into the day plan file. If FORCE is non-nil, insert a diary section even if there is no `planner-diary-string' in the buffer." (interactive "P") ;; sanity check (let ((date (planner-diary-get-name))) (unless (string-match planner-date-regexp date) (error "Cannot insert diary in this buffer")) (planner-diary-update-section date ; file planner-diary-string ; title (planner-diary-get-diary-entries ; text (planner-filename-to-calendar-date ; date date) planner-diary-number-of-days planner-diary-file) force))) (defun planner-diary-insert-diary-maybe (&optional force) "Maybe insert the fancy diary for the day into the day plan file. If the current day is in the past and FORCE is nil, don't do anything. If FORCE is non-nil, insert a diary section even if there is no `planner-diary-string' in the buffer." (interactive "P") (let ((date (planner-diary-get-name))) ;; check if we're in a day plan buffer (if (and (string-match planner-date-regexp date) (or force ; don't care about the date (not (string< date (planner-today))))) ; not past ;; today, future, or force (planner-diary-insert-diary force) ;; we are in the past -> do nothing, message when interactive (when (interactive-p) (message "No day plan buffer or date is in the past. No diary entries inserted."))))) (defun planner-diary-insert-appts (&optional force) "Insert the diary appointments for the day into the day plan file. If FORCE is non-nil, insert a diary appointments section even if there is no `planner-diary-appts-string' in the buffer." (interactive "P") ;; sanity check (let ((date (planner-diary-get-name))) (unless (string-match planner-date-regexp date) (error "Cannot insert diary in this buffer")) (planner-diary-update-section date ; file planner-diary-appts-string ; title (planner-diary-get-appts-entries ; text (planner-filename-to-calendar-date ; date date) planner-diary-appts-number-of-days planner-diary-appts-file) force))) (defun planner-diary-insert-appts-maybe (&optional force) "Maybe insert the diary appointments for the day into the day plan file. If the current day is in the past and FORCE is nil, don't do anything. If FORCE is non-nil, insert a diary appointments section even if there is no `planner-diary-appts-string' in the buffer." (interactive "P") ;; check if we're in a day plan buffer (let ((date (planner-diary-get-name))) (if (and (string-match planner-date-regexp date) (or force ; don't care about the date (not (string< date (planner-today))))) ; not past ;; today, future, or force (planner-diary-insert-appts force) ;; we are in the past -> do nothing, message when interactive (when (interactive-p) (message "No day plan buffer or date is in the past. No diary entries inserted."))))) (defun planner-diary-insert-cal-desk (&optional force) "Insert the cal-desk diary for the day into the day plan file. If FORCE is non-nil, insert a cal-desk diary section even if there is no `planner-diary-cal-desk-string' in the buffer." (interactive "P") ;; sanity check (let ((date (planner-diary-get-name))) (unless (string-match planner-date-regexp date) (error "Cannot insert diary in this buffer")) (planner-diary-update-section date ; file planner-diary-cal-desk-string ; title (planner-diary-get-cal-desk-entries ; text (planner-filename-to-calendar-date ; date (file-name-nondirectory date)) planner-diary-cal-desk-number-of-days planner-diary-cal-desk-file) force))) (defun planner-diary-insert-cal-desk-maybe (&optional force) "Maybe insert the cal-desk diary for the day into the day plan file. If the current day is in the past and FORCE is nil, don't do anything. If FORCE is non-nil, insert a cal-desk appointments section even if there is no `planner-diary-cal-desk-string' in the buffer." (interactive "P") ;; check if we're in a day plan buffer (let ((date (planner-diary-get-name))) (if (and (string-match planner-date-regexp date) (or force ; don't care about the date (not (string< date (planner-today))))) ; not past ;; today, future, or force (planner-diary-insert-cal-desk force) ;; we are in the past -> do nothing, message when interactive (when (interactive-p) (message "No day plan buffer or date is in the past. No diary entries inserted."))))) (defun planner-diary-insert-public (&optional force) "Insert the public diary for the day into the day plan file. If FORCE is non-nil, insert a public diary section even if there is no `planner-diary-public-string' in the buffer." (interactive "P") ;; sanity check (let ((date (planner-diary-get-name))) (unless (string-match planner-date-regexp date) (error "Cannot insert diary in this buffer")) (planner-diary-update-section date ; file planner-diary-public-string ; title (planner-diary-get-public-entries ; text (planner-filename-to-calendar-date ; date date) planner-diary-public-number-of-days planner-diary-public-file) force))) (defun planner-diary-insert-public-maybe (&optional force) "Maybe insert the public diary for the day into the day plan file. If the current day is in the past and FORCE is nil, don't do anything. If FORCE is non-nil, insert a public appointments section even if there is no `planner-diary-public-string' in the buffer." (interactive "P") ;; check if we're in a day plan buffer (let ((date (planner-diary-get-name))) (if (and (string-match planner-date-regexp date) (or force ; don't care about the date (not (string< date (planner-today))))) ; not past ;; today, future, or force (planner-diary-insert-public force) ;; we are in the past -> do nothing, message when interactive (when (interactive-p) (message "No day plan buffer or date is in the past. No diary entries inserted."))))) (defun planner-diary-insert-private (&optional force) "Insert the private diary for the day into the day plan file. If FORCE is non-nil, insert a private diary section even if there is no `planner-diary-private-string' in the buffer." (interactive "P") ;; sanity check (let ((date (planner-diary-get-name))) (unless (string-match planner-date-regexp date) (error "Cannot insert diary in this buffer")) (planner-diary-update-section date ; file planner-diary-private-string ; title (planner-diary-get-private-entries ; text (planner-filename-to-calendar-date ; date date) planner-diary-private-number-of-days planner-diary-private-file)) force)) (defun planner-diary-insert-private-maybe (&optional force) "Maybe insert the private diary for the day into the day plan file. If the current day is in the past and FORCE is nil, don't do anything. If FORCE is non-nil, insert a private appointments section even if there is no `planner-diary-private-string' in the buffer." (interactive "P") ;; check if we're in a day plan buffer (let ((date (planner-diary-get-name))) (if (and (string-match planner-date-regexp date) (or force ; don't care about the date (not (string< date (planner-today))))) ; not past ;; today, future, or force (planner-diary-insert-private force) ;; we are in the past -> do nothing, message when interactive (when (interactive-p) (message "No day plan buffer or date is in the past. No diary entries inserted."))))) ;; UPDATE ALL DIARIES ;;;###autoload (defun planner-diary-insert-all-diaries (&optional force) "Update all diary sections in a day plan file. If FORCE is non-nil, insert a diary section even if there is no section header. Inserts only diaries if the corresponding `planner-diary-use-*' variable is t." (interactive) (when planner-diary-use-diary (planner-diary-insert-diary force)) (when planner-diary-use-cal-desk (planner-diary-insert-cal-desk force)) (when planner-diary-use-appts (planner-diary-insert-appts force)) (when planner-diary-use-private-diary (planner-diary-insert-private force)) (when planner-diary-use-public-diary (planner-diary-insert-public force))) ;;;###autoload (defun planner-diary-insert-all-diaries-maybe (&optional force) "Update all diary sections in a day plan file. If the current day is in the past and FORCE is nil, don't do anything. If FORCE is non-nil, insert a diary section even if there is no section header. Inserts only diaries if the corresponding `planner-diary-use-*' variable is t." (interactive) ;; I intentionally call these individual functions rather than ;; planner-diary-insert-all-diaries. It might make future code changes ;; simpler. (when planner-diary-use-diary (planner-diary-insert-diary-maybe force)) (when planner-diary-use-cal-desk (planner-diary-insert-cal-desk-maybe force)) (when planner-diary-use-appts (planner-diary-insert-appts-maybe force)) (when planner-diary-use-private-diary (planner-diary-insert-private-maybe force)) (when planner-diary-use-public-diary (planner-diary-insert-public-maybe force))) ;;;###autoload (defun planner-diary-show-day-plan-or-diary () "Show the day plan or diary entries for the date under point in calendar. Add this to `calendar-move-hook' if you want to use it. In that case you should also `remove-hook' `planner-calendar-show' from `calendar-move-hook'." (interactive) (or (planner-calendar-show) (and (fboundp 'diary-view-entries) (diary-view-entries 1)) (view-diary-entries 1))) ;;;###autoload (defun planner-diary-insinuate () "Hook Diary into Planner. Automatically insert and update a Diary section in day plan files. This adds a new key binding to `planner-mode-map': C-cC-e updates the diary sections." ;; FIXME: update all diary sections: planner-diary-insert-all-diaries-maybe (define-key planner-mode-map "\C-c\C-e" 'planner-diary-insert-all-diaries-maybe) (add-hook 'planner-goto-hook 'planner-diary-insert-all-diaries-maybe)) ;;;###autoload (defalias 'planner-insinuate-diary 'planner-diary-insinuate) ;;;###autoload (defun planner-diary-add-entry (date time text) "Prompt for a diary entry to add to `diary-file' on DATE. Uses `planner-annotation-functions' to make hyperlinks. TIME and TEXT are used in the description." (interactive (list (planner-read-date nil t) (read-string "Time: ") (read-string "Diary entry: "))) (save-window-excursion (make-diary-entry (concat (let ((cal-date (planner-filename-to-calendar-date date))) (calendar-date-string cal-date t t)) " " time " " text " " (run-hook-with-args-until-success 'planner-annotation-functions)) nil planner-diary-file))) (provide 'planner-diary) ;;; planner-diary.el ends here planner-el/planner-el.texi000066400000000000000000010140301226462314700160510ustar00rootroot00000000000000\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename planner-el.info @settitle planner-el @c %**end of header @dircategory Emacs @direntry * planner-el: (planner-el). planner.el: Day planner/organizer for Emacs. @end direntry @syncodeindex fn cp @copying This manual is for Planner version 3.42. Copyright @copyright{} 2001, 2004, 2005, 2006, 2007, 2008, 2009, 2014 Free Software Foundation, Inc.@* Parts copyright @copyright{} 2005 Jim Ottaway@* Parts copyright @copyright{} 2005 Dryice Dong Liu @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3.0 or any later version published by the Free Software Foundation. A copy of the license is included in the section entitled ``GNU General Public License.'' @end quotation @end copying @titlepage @title Guide to Planner @subtitle a day planner and organizer @subtitle for GNU Emacs and XEmacs @c The following two commands @c start the copyright page. @page @vskip 0pt plus 1filll @insertcopying @end titlepage @c So the toc is printed at the start @contents @ifnottex @node Top, Preface, (dir), (dir) @comment node-name, next, previous, up @top Planner @insertcopying @end ifnottex @menu * Preface:: * Introduction:: * Installation:: * Overview:: A discussion of different approaches to planning * Getting Started:: * More about Planner:: In-depth look at some core features * Managing Your Information:: Integration with external programs * Advanced Configuration:: * Reference Material:: * Getting Help:: * Acknowledgements:: * GNU General Public License:: * Concept Index:: @detailmenu --- The Detailed Node Listing --- Installation * Getting the Files:: * Creating Your Planner:: * Components:: * Advanced Installation:: Getting the Files * Installing from a Source Archive:: * Installing from git:: * Installing from Debian:: Overview * Planning based on the Franklin-Covey Approach:: * Why Use Planner:: Getting Started * Tasks:: * Schedule:: * Notes:: * Hyperlinks:: * Example Page:: * Review:: More about Planner * Navigation:: * More about Tasks:: * More about Notes:: * Making Files Pretty:: * Annotations:: * Interactive Lisp:: planner-lisp.el * Publishing:: planner-publish.el * Experimental Functions:: planner-experimental.el More about Tasks * Creating New Tasks:: * Organizing Your Tasks:: * Task Reports and Overviews:: Creating New Tasks * Creating a Task:: * Task Priorities:: * Task IDs:: planner-id.el * Cyclic Tasks:: planner-cyclic.el * Task Detail:: * Deadlines:: planner-deadline.el Organizing Your Tasks * Multiple Projects:: * Viewing Tasks:: * Modifying Tasks:: * Carrying Over Unfinished Tasks:: * Task Numbering:: * Task Ranks:: planner-rank.el * Grouping Tasks:: planner-trunk.el Task Reports and Overviews * Accomplishments:: planner-accomplishments.el * Status Reports:: planner-report.el * Task Overviews:: planner-tasks-overview.el * tag:: * planner-registry:: Keep track of annotations * planner-zoom:: View and navigate tasks by time period More about Notes * Using Allout Mode:: Quickly navigating your notes * :: Note headlines * :: Index of past notes * Note Indices:: planner-notes-index.el Publishing * Publishing Planner pages:: planner-publish.el * Publishing Calendars:: planner-calendar.el * Authz Access Restriction:: planner-authz.el * RSS Publication:: Sharing notes with planner-rss.el * iCal Task Publication:: Sharing tasks with planner-ical.el * RDF Publication:: planner-rdf.el RDF Publication * Publishing with planner-rdf:: * planner-rdf Tags:: * planner-rdf Usage Examples:: Managing Your Information * E-mail:: Linking notes and tasks to messages * Scheduling and Time:: Tracking appointments and where your time goes * Finances:: Display your account balances and more * Contacts and Conversations:: BBDB and ERC * Tracking Research and Resources:: The Web, bibliographies, and bookmarks * Tracking Development:: E-mail * Unix mail:: Unix mailboxes: planner-unix-mail.el * Gnus:: Gnus mail and news reader: planner-gnus.el * VM:: VM mail reader: planner-vm.el * Wanderlust:: Wanderlust mail reader: planner-wl.el * MH-E:: MH-E mail reader: planner-mhe.el * Rmail:: Rmail: planner-rmail.el Scheduling and Time * Diary:: Using the Emacs diary: planner-diary.el * Appointments:: Appointments in plan pages: planner-appt.el * Timeclock:: Time tracking: planner-timeclock.el * schedule.el:: Project completion: planner-schedule.el Diary * Planner-Diary Advanced Features:: Usage * Task-based Appointments:: * Schedule-based Appointments:: * Viewing Appointments:: * Appointment Updating on Save:: * Appointment and Calendar Integration:: * Appointment Hooks:: Finances * Ledger:: Personal finances: planner-ledger.el Contacts and Conversations * BBDB:: Contacts: planner-bbdb.el * Emacs Relay Chat:: Internet Relay Chat: planner-erc.el Tracking Research and Resources * W3m:: Web browser: planner-w3m.el * BibTeX:: Bibliographies: planner-bibtex.el * Bookmark:: Bookmarks: planner-bookmark.el Tracking Development * Log Edit:: Changelogs: planner-log-edit.el * PSVN:: svn changesets: planner-psvn.el * XTLA:: TLA changesets: planner-xtla.el * Gnats:: Gnats: The GNU bug reporting system Advanced Configuration * Customizing Your Day Pages:: Change your templates * Variables to Customize:: Change various aspects of Planner behavior * Ideas for Other Keybindings:: Add to and change the default keybindings Reference Material * Keeping Track of Time:: * Other Interactive Functions:: * Planner Keybindings:: Default keybindings for Planner * Sample Configuration Files:: Sample Configuration Files * File Organization:: * Bare-Bones Planning:: * Bare-Bones Planning with Plan Pages:: * Tasks on Plan Pages with Some Day Pages:: * Hierarchical Tasks:: @end detailmenu @end menu @node Preface, Introduction, Top, Top @comment node-name, next, previous, up @chapter Preface This document describes Planner, which was written by John Wiegley and is now maintained by John Sullivan (@pxref{Acknowledgements}). This document is a work in progress, and your contribution will be greatly appreciated. Please e-mail comments and suggestions to the mailing list (@pxref{Getting Help}). In the subject line of your e-mail, include the word @samp{Planner}. This documentation is available in eye-pleasing formats including PDF and HTML at @url{http://wjsullivan.net/static/doc/planner/}. Documentation author and maintainer: John Sullivan @email{john@@wjsullivan.net} @* John Sullivan (johnsu01)@* April 25, 2004 @node Introduction, Installation, Preface, Top @comment node-name, next, previous, up @chapter Introduction Planner is an organizer and day planner for Emacs. It helps you keep track of your pending and completed tasks, daily schedule, dates to remember, notes and inspirations. It is a powerful tool not only for managing your time and productivity, but also for keeping within easy keystroke reach all of the information you need to be productive. It can even publish reports charting your work for your personal web page, your conscience, or your soon-to-be-impressed boss. In fact, because it uses as its building blocks simple plain-text files, it is an incredibly modular and flexible tool capable of shaping and handling your personal information in ways whose variety is limited only by your imagination. Because of this, Planner has a very active and generous community who regularly share their innovations with each other. Many of these modules and extensions are included in the archive that you will download. Once you get the basics down, you'll probably want to explore some of them. But as you read this manual and work with Planner, keep in mind that the basic core is actually very simple, and it might be worth spending time with just that before delving into the customizations. Because they are plain text with very few requirements, the organizer pages kept by Planner can be as basic or as detailed as you like. Your pages can be simple to-do lists with no more additional information than what you would scrawl on a napkin, or they can be a highly technical affair involving hyperlinks, embedded Lisp code, appointment schedules and RSS feeds. As with so much in Emacs, it's all up to you. To get started with Planner, you first need to download it, and possibly also the packages it depends on (@pxref{Installation}). @node Installation, Overview, Introduction, Top @comment node-name, next, previous, up @chapter Installation @cindex installation Planner depends on Muse. Information for downloading and installing Muse can be found at @url{http://mwolson.org/static/doc/muse.html}. Planner and Muse are intended to work with version 21 or later of Emacs and XEmacs. Make sure that you use the latest Muse release. Development code might prove unstable. @menu * Getting the Files:: * Creating Your Planner:: * Components:: * Advanced Installation:: @end menu @node Getting the Files, Creating Your Planner, Installation, Installation @comment node-name, next, previous, up @section Getting the Files Currently, there are three ways to obtain and install Planner. You can install it from a source archive, git, or Debian package. @menu * Installing from a Source Archive:: * Installing from git:: * Installing from Debian:: @end menu @node Installing from a Source Archive, Installing from git, Getting the Files, Getting the Files @comment node-name, next, previous, up @subsection Installing from a Source Archive @cindex source code archive, installing from You can install Planner from the source archive packaged and distributed directly by the maintainer. This archive is provided in both @file{.tar.gz} and @file{.zip} format. If you don't know where to extract these archives, create a @file{~/elisp} directory, and extract them there. @enumerate @item Download and unpack either @url{http://mwolson.org/static/dist/planner-latest.tar.gz} or @url{http://mwolson.org/static/dist/planner-latest.zip}. @item Likewise for @url{http://mwolson.org/static/dist/muse-latest.tar.gz} or @url{http://mwolson.org/static/dist/muse-latest.zip}. @item Likewise for @url{http://mwolson.org/static/dist/remember-latest.tar.gz} or @url{http://mwolson.org/static/dist/remember-latest.zip}. @item Edit your @file{~/.emacs} (@file{_emacs} on Microsoft Windows). Replace @file{/path/to} with wherever you extracted the files. @example ;; Add the directories to your load path (add-to-list 'load-path "/path/to/muse/lisp") (add-to-list 'load-path "/path/to/planner") (add-to-list 'load-path "/path/to/remember") ;; Load planner (require 'planner) @end example @end enumerate @subheading Updating Your Version Download a new version and extract it over the old directory. Don't forget to delete any byte-compiled files (@file{*.elc}) in the directories (which can be accomplished by running ``make clean'') so that the new code will be used. @node Installing from git, Installing from Debian, Installing from a Source Archive, Getting the Files @comment node-name, next, previous, up @subsection Installing from git @cindex git version control system, using The git version control system allows you to keep up-to-date with the latest changes to the development version of Planner. It also allows you to contribute changes (via commits, if you are have developer access to the repository, or via patches, otherwise). If you would like to contribute to Muse development, it is highly recommended that you use git. Debian users can install git with @kbd{apt-get install git}. If you are new to git, you might find this tutorial helpful: @uref{http://www.kernel.org/pub/software/scm/git/docs/tutorial.html}. Downloading Planner with git and staying up-to-date involves the following steps. @example # Retrieve Muse git clone git://repo.or.cz/muse-el.git muse # Retrieve Planner git clone git://repo.or.cz/planner-el.git planner # Retrieve Remember git clone git://repo.or.cz/remember-el.git remember # If that didn't work (due to a restrictive firewall), then try the # following instead: # # git clone http://repo.or.cz/r/muse-el.git muse # git clone http://repo.or.cz/r/planner-el.git planner # git clone http://repo.or.cz/r/remember-el.git remember @end example Then add the following lines to your @code{~/.emacs}: @example ;; Add the directories to your load path (add-to-list 'load-path "/path/to/muse/lisp") (add-to-list 'load-path "/path/to/planner") (add-to-list 'load-path "/path/to/remember") ;; Load planner (require 'planner) @end example You can also browse Planner's git repository on the web at @url{http://repo.or.cz/w/planner-el.git}. @subheading Updating Your Version @cindex git, updating with To stay up-to-date using git, here are some commands that might be useful. To list upstream changes not in local copy: Do this whenever you want to see whether new changes have been committed to Planer. If you wish, you may skip this step and proceed directly to the ``update'' step. @example # Change to the source directory you are interested in. Example: cd muse/ # Fetch new changes from the repository, but don't apply them yet git fetch origin # Display log messages for the new changes git log HEAD..origin @end example ``origin'' is git's name for the location where you originally got Muse from. You can change this location at any time by editing the @file{.git/config} file in the directory where the Planner source was placed. To update to the latest version: @example cd muse; git pull cd ../planner; git pull cd ../remember; git pull @end example Don't forget to either rerun the @command{make} command or delete the byte-compiled files (@file{*.elc}) in the directories, so that the new code will be used. @node Installing from Debian, , Installing from git, Getting the Files @comment node-name, next, previous, up @subsection Installing from Debian @cindex Debian package Debian packages for Planner and Muse are available in Debian proper as the @code{planner-el} and @code{muse-el} packages, respectively. If you wish to try experimental packages, add the following lines to your @file{/etc/apt/sources.list} @example deb http://mwolson.org/debian/ ./ @end example Then, do the following steps as root: @example apt-get update apt-get install muse-el apt-get install planner-el @end example If you get some warning about the key not being trusted, you can either ignore it or do the following. @example gpg --keyserver pgpkeys.mit.edu --recv-key f3a8d319 gpg -a --export f3a8d319 | sudo apt-key add - @end example @subheading Updating Your Version @cindex Debian package, updating If you installed Planner from Debian, do @kbd{apt-get update; apt-get upgrade} to upgrade all packages that can be upgraded, or @kbd{apt-get update; apt-get install planner-el} to upgrade just planner-el. @node Creating Your Planner, Components, Getting the Files, Installation @section Creating Your Planner Now that you have installed the files for Planner and Muse, you need to set some options to create your first planner. Muse thinks in terms of projects. Each project consists of a group of documents and certain information associated with these documents. Planner is organized as a project within Muse. So, you need to tell Muse a bit about it. Add something like the following code to your @file{.emacs} file. First, give your new Planner project a name. In this case, we use the name, ``WikiPlanner''. @example (setq planner-project "WikiPlanner") @end example Next, add an entry for your project to Muse's master list of projects. Don't forget to use your own name here in place of ``WikiPlanner'' if you have chosen something different. @example (setq muse-project-alist '(("WikiPlanner" ("~/Plans" ;; where your Planner pages are located :default "TaskPool" ;; use value of `planner-default-page' :major-mode planner-mode :visit-link planner-visit-link) ;; This next part is for specifying where Planner pages ;; should be published and what Muse publishing style to ;; use. In this example, we will use the XHTML publishing ;; style. (:base "planner-xhtml" ;; where files are published to ;; (the value of `planner-publishing-directory', if ;; you have a configuration for an older version ;; of Planner) :path "~/public_html/Plans")))) @end example This code should work fine as-is for you as long as the directories you see exist, and as long as you have no other Muse projects besides your planner. The first directory (@file{~/Plans}) is the directory where the source files for your planner will reside. This is the directory where you will actually visit files and edit them. These files must have a ``.muse'' extension. The second directory (@file{~/public_html/Plans}) is the directory where your planner files will be published by Muse as XHTML (@pxref{Publishing}). After you have added this code, make sure to either evaluate it or restart Emacs. @node Components, Advanced Installation, Creating Your Planner, Installation @comment node-name, next, previous, up @section Components Now that you have the archive, let's look at what's in it. There should be three directories, named @file{planner}, @file{muse} and @file{remember}. In the @file{planner/} directory, you'll see many files with names like @file{planner-gnus.el}. These are extra modules and extensions for Planner, which you can use to tailor Planner to fit your desired planning and information management habits. In the @file{muse/lisp} directory, you'll see many files with names like @file{muse-blosxom.el}. As in @file{planner/}, these are optional modules and extensions. A minimal working installation includes just @file{planner/planner.el}. You need @file{planner.el} because it provides the core functions for handling tasks, notes, and page navigation. You need @file{Emacs Muse} because it provides the functions used to display your pages (both in an emacs buffer and as HTML), and for connecting them to each other. More specifically, it enables you to have hyperlinks and formatting in your emacs buffers even though the actual files you are working with are saved in plain text. These abilities are used in Planner to format your planner pages the way you like, to create links from your tasks and notes to the materials and projects they refer to, and to optionally ``publish'' your pages in different formats, including HTML. In the @file{remember/} directory are files related to RememberMode. RememberMode does not depend on Planner or Muse, but works best with Planner installed. It is not required in order to use Planner, but it is used by many Planner users to record notes and information to their planner pages. If you are curious, you can open each file in these directories and read the comments at the top, to get an idea of what each extension is used for. They are also all detailed later in this manual. @node Advanced Installation, , Components, Installation @comment node-name, next, previous, up @section Advanced Installation Once you decide you want to keep Planner around for a while, there are two additional steps you can take to make using it easier and more efficient. These steps are optional. @itemize @cindex installing the info file @cindex @file{planner-el.texi}, installing @cindex @file{planner-el.info}, installing @item You can make this document, the Planner info file, appear in the index of info files you see when you type @command{M-x info} or @kbd{C-h i} in Emacs. The instructions for doing this vary depending on whether you have permission to edit certain files on your system. Follow the instructions in @ref{Installing an Info File, , ,texinfo, Texinfo}, using something like: @example * Planner: (path/to/planner/Planner). Organizer/day planner for Emacs. @end example for the new entry in the info @file{dir} file. @cindex byte compiling @item You can byte-compile @file{planner.el}, @file{Muse}, @file{remember.el}, or any of the optional modules you frequently use, in order to improve the speed of their execution. Basically, all you need to do is (1) change the directory for each project listed in @file{scripts/planner-build.el}, (2) copy @file{Makefile.defs.default} to @file{Makefile.defs} and edit it as needed, and (3) run @command{make} from the command line. To read more detail about byte compilation, see @ref{Byte Compilation, , ,elisp, Emacs Lisp Reference Manual}. @end itemize @node Overview, Getting Started, Installation, Top @comment node-name, next, previous, up @chapter Overview Planner is a plain-text hyperlinked personal information manager for Emacs that helps you keep track of tasks, notes, and other information. People use Planner to support different ways of planning one's day, from Franklin-Covey and David Allen's Getting Things Done to home-brew hacks. Planner is even used to manage information not normally handled by a personal information manager, like bugtracking, time tracking, and team data. If you start by using Planner as a basic TODO and notes manager, you might find other ways it can help you improve your process. You can use Planner to keep track of your tasks, schedule, notes, and other information you want to store in hyperlinkable text files. You can get the most benefit out of a personal information manager if you use it everyday. Most people add @code{(plan)} to the end of their @file{~/.emacs} so that Planner shows today's schedule and unfinished tasks whenever Emacs starts. If you leave your Emacs running for more than 24 hours, try to get into the habit of running @code{plan} at least once a day. Because your time is important, Planner tries to minimize distractions, making it easier for you to jot down tasks and notes without being distracted from your work. People often make tasks based on the current buffer, so Planner tries to create hyperlinks to whatever you're looking at so that you can jump back to it easily. The @ref{Getting Started} tutorial will show you how to set that up for both tasks and notes. The customizability of Planner means you can make your personal information manager truly personal. Planner strives to be as flexible as possible, and we would love to adapt Planner to fit your needs. Browse through our mailing list (@pxref{Getting Help}) to find out how other people are using Planner, and post your feature requests and bug reports there! Planner is just a tool. It does not dictate a particular way of planning, although it supports some ways better than it supports others. If you want to take some time thinking about planning, read the following reflections for inspiration and ideas. On the other hand, if you want to hit the ground running, see @ref{Getting Started}. If you already have a specific way of planning in mind, check out @ref{Sample Configuration Files}. @menu * Planning based on the Franklin-Covey Approach:: * Why Use Planner:: @end menu @node Planning based on the Franklin-Covey Approach, Why Use Planner, Overview, Overview @comment node-name, next, previous, up @section Planning Based on the Franklin-Covey Approach @cindex philosophy of planning (This is an edited and updated version of an essay originally by John Wiegley. Read it if you want to get some insights into one way of planning. You can skip this if you want to go straight to planning your day.) What is planning? It can be a nebulous thing to define. In its essence, however, it is very simple: it's how we achieve our dreams. Our days are filled with time, and hence with actions, whether they be of a mental or physical sort. But there are two kinds of action: reactive and creative. Reactive action is a response to the environment, a reaction to stimulus. Had we enough instincts to ensure survival, we could live according to this kind of action alone. It is a mode of behavior we share with every living species. The opposite to reactivity is creativity, when we decide upon a course of action that is a wholly a product of personal choice. We then make decisions as to the steps needed to make this wish a reality. This is planning. Planning is essentially a creative endeavor at every step. First, create the idea, what you want to achieve. Very short-term ideas do not need much more than thinking about how to do it. But long-term ideas require planning, since the mind cannot contain all of the details. Second, decide how the idea maps into the circumstances you find yourself in. Some environments will assist your plan, others hinder it. But step by step, identify every barrier to the realization of your idea, and devise a countermeasure to overcome it. Once you've mapped things out from beginning to end, accounting for unknowables as best you can, you now have your plan. Third is to break the stages of the plan into parts that are not overwhelming in their complexity. It is at during this phase that a plan is turned into task items, each to be accomplished within the span of one day's time. If a task requires several days, break it up further. The smaller it is, the less your mind will recoil from attempting it. Fourth is to monitor your progress, identifying problems and correcting for them as you go. Some plans start out unachievable, and remain that way indefinitely, due to a simple lack of observation. If nothing is working for you, change it. Otherwise, your plan is merely a well-crafted wish. Fifth is just to do the work, and be patient. All good plans take a great deal of time, and *cannot* happen immediately. The groundwork must be laid for each step, or else it will rest on an insecure foundation. If you follow your plan doggedly, applying some time to it each day or week, it @emph{will} happen. Remember the story of the tortoise and the hare. I've even written a short essay on the necessity of gradual accomplishment, which can be found at @url{http://www.johnwiegley.com/2004/03/advancing-the-process.html}. How can this software help? Computers are ideal for manipulating information, since they allow you to change things without erasing or rewriting. And since all plans change quite a bit during their implementation, a planning program can be very helpful. Start by installing Planner and Muse (@pxref{Installation}). Now, conceive your idea. I can't believe there's nothing you want from life. More peace, time to enjoy the world, an end to war? Everyone wants something. Search deeply, and you will find countless unhoped wishes lurking therein. Choose one for now, and think on it for a while. Then open a file (using @kbd{C-x C-f}) within the directory you named in your @code{muse-project-alist}. Make sure the file has a @file{.muse} extension so that Emacs will automatically recognize it as a planner file. Name the file after your plan, such as @file{BetterHealth.muse}. Choose an idea you really want to accomplish. Struggle to differentiate between the things you want because others want them, and the things you want for yourself. It takes quite an effort, and may require a long time before you notice the difference. Many people want to be more healthy to be more attractive, which is an externally driven goal. Unless @emph{you} really want to accomplish what you envision, the odds are you will fail. Only our own wishes and dreams possess enough personal energy to see themselves to fruition. What happens to many of us is simply that we never become conscious of these dreams: what we love, what we desire most. When I talk to friends, so much of what I hear is things they want because they feel they should want them. There's just not enough energy there to pursue a good plan, because nearly all of it is negative energy. Do you know what you really want? Don't worry, many people don't. It's not a question anyone really wants us to pursue, because often we don't want what others do; it doesn't contribute to the social welfare, and all that nonsense. Somehow we always forget that what's good for the social welfare now, was someone else's crazy dream a hundred years ago. The human aversion to fundamental change is always one's greatest enemy, so don't waste any time getting bitter about it. For the sake of argument I assume you really do want to be healthier, because you've fallen in love with the ideal of purity, or you understand the connection between your physical self and the world around you, and how this can open up your spirit to desiring more. I assume. :) So you're in a Wiki file called @file{BetterHealth}. Start typing. Type anything related to your idea: what you think about it, your ideas on it, @emph{and especially what the end will look like}. If you can't visualize the end, you can't plan, since planning is about drawing a line between now and then. When you've typed enough to gain a vision of your goal, start drafting what the possible intermediate steps might be. Then stop, get up, walk around, enjoy life, and come back to it. Taking a long time at the beginning is not a bad idea at all, as long as it's not forever. As you chew on your idea, it will begin to become more and more concrete. You'll have ideas about the smallest pieces, and ideas about the biggest pieces. Keep going until it starts to take shape before you, and you can see yourself in your mind's eye moving from the present into the future. Write down this progression, and the sorts of things you might encounter along the way. As you continue, you'll naturally discover discrete phases, or ``milestones'' as managers love to call them. These are very important, because they let you know you're making progress. I recommend having a big party with friends every time you achieve a milestone. A typical plan might have between three and ten. Between the milestones are the bigger pieces of your plan. You might find it convenient to name these pieces using MixedCase words. Try adding these lines to your @file{.emacs} or @file{_emacs} file. @example (require 'muse-wiki) (setq muse-wiki-allow-nonexistent-wikiword t) @end example You'll notice that Emacs colors and underlines them for you. Like, FindGoodGym. Hit return on this highlighted word, and you'll find yourself in another, blank file. In this file, start drafting your sub-plan, just as you did with the larger plan. You should find it easier now, since the scope is smaller. As you break down further, you'll notice simple little things that need to get done. These are your tasks. Every plan is a succession of tasks. The difference from reactivity is that each task is part of the larger plan. This is what it means to be systematic: that everything you do helps further your plan. If you have tasks in your day that contribute to no plan, they are reactive. Of course, life is full of these, but don't let them take up more than 20% of your day. If you allow yourself to be dominated by reactive tasks, you'll regret it at the end of your life. I don't know this personally, but I do know that striving for one's dreams -- and seeing them come to fruition -- is the greatest joy a man can possess. It is the essence of freedom, of living, of creation. Reactivity is the opposite of this, and serves only to drain our energy and slacken our spirits. Now that you've thought of a simple task, type @kbd{C-c C-t}. This will ask for a brief description of the task, and when you plan to do it. If you hit @key{RETURN} at the question @samp{When}, it assumes you mean today. It will also pop up a three-month calendar at this question, so you can see where your free days are. Make sure you set the variable @code{mark-diary-entries-in-calendar} to @samp{t} in your @file{.emacs} (or @file{_emacs}) file. This way, you can see which days your appointments fall on. (Read about the Emacs Calendar and Diary in @ref{Calendar/Diary, , , Emacs, GNU Emacs Manual}.) @example (setq mark-diary-entries-in-calendar t) @end example Once your task is in there, go back to your plan and keep generating more tasks. Generate them all! Fully describe---as tasks---everything necessary to bring your sub-plan to completion. Don't create tasks for the other sub-plans. You may have good idea of what they'll look like, but don't bother rendering them into tasks just yet. Things will change too much between now and then, for that to be a good use of your time. Is your sub-plan now rendered into all of the tasks necessary to reach your first milestone? Great! That is the purpose of planner.el. The rest is really up to you. If you find that you keep putting things off, and never do them, that's the surest sign you're planning for someone else's dream, and not your own. Here are some of the things planner.el can do, to help you manage and track your tasks: At the beginning of every day, type @kbd{M-x plan}. This will jump you to the top of the most recent task list before today. If you skipped a bunch of days, you'll have to open up those files on your own. Probably some of the tasks that day won't be finished -- that's OK. Learning to properly estimate time is a magical, mystical art that few have mastered. Put your cursor on those undone tasks, and type @kbd{C-c C-c}. This will move them into today's task page. You can jump to today's task page at any time by typing @kbd{C-c C-n} (from a Wiki or planning page). I heartily recommend binding @kbd{C-c n}, to jump you to this page from anywhere: @example (define-key mode-specific-map [?n] 'planner-goto-today) @end example As you look at your task sheet each day, the first thing to do is to ``clock in'' to one of them. This isn't necessary, and is only helpful if you're around your computer a lot. But by typing @kbd{C-c C-i} (assuming you have @file{timeclock.el} on your load-path), it will log the time you spend working on your sub-plan (@pxref{Time Intervals, , , Emacs, GNU Emacs Manual}). This is helpful for viewing your progress. Type @kbd{C-c C-o} to clock out. @kbd{C-M-p} and @kbd{C-M-n} will move a task up and down in priority. Priority is represented by a letter A through C. 'A' tasks mean they must be done that day, or else your plan is compromised and you will have to replan. 'B' means they should be done that day, to further the plan, otherwise things will be delayed. 'C' means you can put off the task if you need to, although ultimately it will have to be done. For reactive tasks, the letters mean something different: 'A' means you must do it today, or somebody will roast your chestnuts over an open fire. 'B' means you should do it today, or else someone will be practicing patience at the day's end. 'C' means no one will notice if you don't do it. Again, reactive tasks are ENEMIES OF PLANNING. Really, until you see them that way, circumstances will push you around and steal your life away. We have only so many years to use, and everyone is greedy to take them. It's insidious, almost invisible. A healthy dislike of reactivity will do wonders for organizing your affairs according to their true priority. The last word that needs to be said concerns ``roles''. Every person stands in several positions in his life: husband, employee, manager, etc. These roles will tend to generate tasks not associated with any immediate plan, but necessary to maintain the health and functioning of the role. My suggestion is to keep this the smallest possible number, and fulfill those that remain well. How you decide to apportion your time between pursuing grand designs, and fostering deep relationships, is a personal matter. If you choose well, each will feed the other. I mention this to point that reactivity is something not exclusively associated with tasks that have no master plan, because being a father, for example, is something that rarely proceeds according to orderly plans. But the role of father itself is its own plan, whose goal is ``to be the best one can'', and whose component tasks are spending time on whatever comes up. It is, in a sense, an implicit plan. But reactive tasks follow no plan at all; they are parasites of time that suck the spirit away, whereas properly chose roles actually help fulfill one's own inner needs. At least, this is what I believe. @defun plan force-days Start your planning for the day, beginning with the last day's tasks. If @code{planner-carry-tasks-forward} is non-nil, find the most recent daily page with unfinished tasks and reschedule those tasks to the current day. If @var{force} is non-nil, examine all past daily pages for unfinished tasks. If @code{planner-carry-tasks-forward} is nil, visit the most recent daily page. If a daily page for today exists, visit that instead. If @var{force-days} is a positive integer, scan that number of days. If @var{force-days} is @samp{t}, scan all days. @end defun @node Why Use Planner, , Planning based on the Franklin-Covey Approach, Overview @comment node-name, next, previous, up @section Why Use Planner? @cindex Planner, why use You can skip this essay if you just want to get started, or read it for some insights into why the previous maintainer is crazy about it. Why I Use Planner, by Sacha Chua I thought about why I liked Planner. Planner as a TODO manager isn't particularly special. Although I can assign tasks to categories and see a breakdown of what projects are taking up my time, Evolution and Microsoft Outlook provide more powerful task support. In other task managers, you can e-mail tasks, assign multiple categories and fill in all sorts of metadata. You can even synchronize your tasks with devices like a phone or PDA. So why use Planner? I realized that integration into my way of life and automatic context clues are what really make planner tasks worth it for me. I don't have to switch to another application to create a task. I can just hit a keyboard shortcut. Planner uses a minibuffer to get the task description. My windows are not rearranged in any way, and I can look at the data that's relevant to a task. Not only that, tasks automatically pick up context clues, like whom I'm talking to on IRC or the file I'm editing at the moment. This cuts down on the explicit context I need to include and makes it easier for me to bring up the task again. As a scheduler, Planner is also not particularly distinguished. Sure, it can display my @file{~/diary}, but for that matter so can @kbd{M-x diary}. Evolution and Outlook can give me a more graphical view of my time, sync with my PDA, and coordinate my schedule with other people. Those applications support detailed schedule entries with powerful cyclic options. On the other hand, Planner gives me a personal, plain text view and (at least the way I use it) requires me to edit a separate file to add new appointments. (I've defined a few shortcut keys to deal with this.) However, it does have one advantage---my schedule is always loaded. I used to use Outlook on Windows, but having my schedule in a separate application meant that I actually looked at it very rarely, as I had turned off reminders because they got annoying. Planner's notes, however, are what really convinced me. I can hit a keyboard shortcut from anywhere and type my notes into a buffer which automatically keeps context information. After typing the note, I can then categorize it. I think that the critical thing here is that interruptions---fleeting thoughts---don't break my flow. I can just pop up a remember buffer, stow that thought away somewhere, and go back to it whenever I want. In contrast, creating a note in Outlook means switching out of my application, making a couple of keystrokes, typing the note in, and then switching back. The context switches make it hard to keep track of where I am and what I'm supposed to remember. Not only that, I need to enter context by hand. Even though I can color my notes and reorganize them in Outlook, I find the context switch too expensive. I used to keep notes in other knowledge management tools as well. Some applications allowed me to drag-and-drop links into the current note, and that was cool. But that required a manual action, and those applications didn't feel integrated into my way of working. (Note: You'll need remember.el for this.) I guess that's why I like Planner. Unlike other organizers which don't know anything about the applications I use, Planner tries its best to integrate into the way I work, and it's easy to extend. Fortunately I do almost all my work in Emacs, so I can think of my organizer as integrated into my e-mail client, Internet Relay Chat client, web browser, file editor and even games. It automatically picks up context clues from these applications and allows me to easily jump back to relevant files. It doesn't distract me. It allows me to key in data and then it gets out of my way. (That said, it's perfectly okay to use Planner even if you don't live in Emacs.) The processing that happens in the background is a bonus, and publishing my task list and notes online has greatly helped me. It gives other people a way to see what I'm working on and what I've planned for the future. Occasionally people write in with additional resources and helpful tips. (Again, this is purely optional. Many people don't publish their planner pages. Other people use really fine-grained access control.) I think the greatest feature of Planner, though, is its user community. Because Planner can be easily modified, we can experiment with a lot of new ideas quickly, and we can tailor Planner to fit our needs. I love checking my @samp{planner-el-discuss} mail and finding out how people have tweaked Planner or would like to tweak Planner, and I've learned a lot by exchanging reflections on organizing one's life. I really wasn't an organization freak before I started using Planner. I often forgot to do my homework or answer important mail. I still procrastinate now, but at least it's all being kept track of somewhere! I also really like how Planner lets me to gradually improve how I'm doing things, and I feel I've come a long way. Please try it out! We'd love to hear how Planner can become @emph{your} personal information manager. @node Getting Started, More about Planner, Overview, Top @comment node-name, next, previous, up @chapter Getting Started At the end of this tutorial, you will be able to use Planner and related modules to keep track of your tasks, schedules and notes, all within the convenience of Emacs. There are two kinds of pages in a Planner wiki. Day pages show tasks, schedule, and notes for the day, while plan pages organize related tasks and notes into a single page. If you have not yet added planner to your @file{~/.emacs}, add the following lines: @example (add-to-list 'load-path "/path/to/muse/lisp") (add-to-list 'load-path "/path/to/planner") (add-to-list 'load-path "/path/to/remember") (require 'planner) @end example This will bring up the most recent day page with unfinished tasks or create a new day page if necessary. By default, planner pages are stored in @samp{~/Plans}. @menu * Tasks:: * Schedule:: * Notes:: * Hyperlinks:: * Example Page:: * Review:: @end menu @node Tasks, Schedule, Getting Started, Getting Started @section Tasks Let us start by creating a task labelled @example Join http://mail.gna.org/listinfo/planner-el-discuss/ @end example From anywhere (even this info buffer!), call @kbd{M-x planner-create-task-from-buffer} to create a new task. Fill in the description and choose a date by: @itemize @item typing 1 - 31 to put the task on that day of the month, @item accepting the default (today) by pressing RET, @item selecting the date with mouse-1, @item typing +n (where in is an integer) to schedule the task in n days time, or @item typing nil to make an undated task. @end itemize For now, accept the default (@samp{today}) by pressing @key{RET}. You will then be prompted for a plan page. Plan pages gather related tasks and notes, giving you an overview of what you've done so far. You can accept the default TaskPool, create your own plan page, or specify nil to make a task that is not associated with a plan page. For now, accept the default (@samp{TaskPool}) by pressing RET. You have created your first task. View today's page with @kbd{M-x planner-goto-today}. You will see a line of the form @example #B _ Join http://mail.gna.org/listinfo/planner-el-discuss/ (TaskPool) @end example If you created the task from this page, then there will be an additional annotation: @example #B _ Join http://mail.gna.org/listinfo/planner-el-discuss/ : Tasks (TaskPool) @end example The URL, @samp{TaskPool} and @samp{Getting Started} are hyperlinks. You can use TAB and S-TAB to navigate between them and RET to follow the link. Create more tasks using @kbd{M-x planner-create-task-from-buffer}. This is bound to @kbd{C-c C-t} in @code{planner-mode} pages for your convenience. For example, create the following tasks: @itemize @item @samp{Describe my current way of working and how I would like to work}, for three days from now (@samp{+3}), @item @samp{Learn how to schedule a task}, an undated task (@kbd{nil}) on the TaskPool page, @item @samp{Browse through the Planner info manual} for today (@kbd{.} or accept the defaults), and @item @samp{Add (plan) to the end of my [[~/.emacs]]} for today, but without a plan page (specify @kbd{nil} at the plan page prompt) @end itemize Tip: I bind planner-create-task-from-buffer to "F9 t" so that I can easily call it from anywhere. You can do that with this elisp fragment: @code{(global-set-key (kbd " t") 'planner-create-task-from-buffer)} Next, visit the TaskPool by: @itemize @item @key{TAB}-bing or using the cursor and typing @key{RET} to follow the link, @item @kbd{C-x C-f TaskPool RET} to use @code{find-file}, or @item @kbd{C-c C-f TaskPool RET} to use @code{muse-project-find-file} @end itemize You can see an overview of the tasks as scheduled on different days. Unlike many personal information managers that store all of your data in one file and then perform magic in order to present different views, Planner uses plain text files. The data is duplicated and kept updated by functions. This makes it simpler and easier to modify, because what you see is (almost) what you get. On the other hand, you'll need to get used to either editing both files, or using the built-in functions for editing and updating files. If you prefer not to work with linked tasks, you can configure Planner to use only plan pages or use only day pages. The TaskPool page should list the tasks you created earlier. Go to the one named Learn how to schedule a task . Type @kbd{C-c C-c} (@code{planner-copy-or-move-task}) to schedule the task. Type RET to accept the default (today). Go to the day page by following the link or calling @kbd{M-x planner-goto} (@kbd{C-c C-j C-d} or the menu bar); you will see the newly-created task there. You can also use @kbd{C-c C-c} (@kbd{planner-copy-or-move-task}) to reschedule a task to an earlier or later date. Well, that task is done. To mark the task as completed, type @kbd{C-c C-x} (@code{planner-task-done}). You can also edit the status manually (change _ to X) as long as you remember to call @kbd{M-x planner-update-task} to update the link page as well. Updating relies on the task description being the same, so do not edit this manually. Quick summary of commands: @itemize @item Go to today's page: @kbd{M-x plan} to carry unfinished tasks forward, or @kbd{M-x planner-goto-today} to just go to today's page. @item Create a task: @kbd{C-c C-t} (@code{planner-create-task-from-buffer}), or type a task manually (call M-x planner-update-task if the task is linked) @item Mark a task as done: @kbd{C-c C-x} (@code{planner-task-done}), or edit the task and call @kbd{M-x planner-update-task} @item Edit a task description: @kbd{M-x planner-edit-task-description} @item Reschedule a task: @kbd{C-c C-c} (@code{planner-copy-or-move-task}) @item Reschedule many tasks: Mark a region and use @kbd{M-x planner-copy-or-move-region} @item Change the plan of a task: @kbd{M-x planner-replan-task}, or do @kbd{C-c C-c} (@code{planner-copy-or-move-task}) and type in a plan page rather than a date @item Delete a task: @kbd{M-x planner-delete-task} @item Reorder tasks: @key{M-p} (@code{planner-raise-task}) and @key{M-n} (@code{planner-lower-task}), or normal editing commands like kill and yank @item Change task priorities (@samp{#A} > @samp{#B} > @samp{#C}): @key{C-M-p} (@code{planner-raise-task-priority}) and @key{C-M-n} (@code{planner-lower-task-priority}), or edit the task and call @kbd{M-x planner-update-task}. @end itemize You can save your tasks with @kbd{C-x C-s} the same way you save any other file, or Emacs will prompt you to save it when you exit. @node Schedule, Notes, Tasks, Getting Started @comment node-name, next, previous, up @section Schedule This is free-form. You can put anything you want into this, or remove it from @code{planner-day-page-template} entirely. Some people use it to keep track of their plans for the day with tables like this: @example hh:mm | hh:mm | activity hh:mm | hh:mm | activity hh:mm | hh:mm | activity @end example Remember, Planner files are just plain text. You can add new sections or remove old ones, or use the suggested sections for entirely different activities. @node Notes, Hyperlinks, Schedule, Getting Started @comment node-name, next, previous, up @section Notes @cindex @file{remember.el} @cindex @file{remember-planner.el} @cindex notes By default, your Planner pages will have a Notes section. You can put anything you want in this section, or remove it from your @code{planner-day-page-template} entirely. You may be interested in @file{remember-planner.el}, part of the Remember package (see @pxref{Top, Remember,,remember}) @code{remember-planner.el} makes it easy to create notes from anywhere in Emacs, and it uses the same context-sensing code that Planner uses. Notes added by @code{remember-planner.el} look like this: @example .#1 Headline 00:00 Body [[context hyperlink]] @end example and are outlined at the H2 level in published HTML. You can easily create context-aware notes if you include the following in your @file{~/.emacs}: @example (require 'remember-planner) (setq remember-handler-functions '(remember-planner-append)) (setq remember-annotation-functions planner-annotation-functions) @end example Then @kbd{M-x remember} will open a dedicated buffer for you to write your note. If Planner recognizes your current buffer as one with context then it will include a hyperlink at the bottom of the note. The first line of the note is used as a title, so make it short and meaningful. The rest of the text will be used as the body. Try it now by creating a note, perhaps about things you'd like to remember from this tutorial. Typing @kbd{C-c C-c} after composing will prompt for a plan page to put the note on, with auto-completion. If you don't enter a page, the note will just be saved on today's page. If you do specify a plan page, the note will go on both today's page and on the specified page. Let's try specifying @samp{TaskPool} for the note. If you look at today's page, you'll find a timestamped note that links to @samp{TaskPool}. Likewise, @samp{TaskPool} contains a note that links to today's page. To change the plan page of a note, use @kbd{planner-replan-note}. If you decide to edit the note on one of these pages after it has been saved, be aware that your changes will not be automatically reflected on the linked page. To update the linked page after editing a note, use @kbd{M-x planner-update-note}. @node Hyperlinks, Example Page, Notes, Getting Started @section Hyperlinks @cindex hyperlinks Planner automatically creates context-sensitive hyperlinks for your tasks and notes when you use @code{planner-create-task-from-buffer} and @code{remember}. Blue links indicate URLs and Planner pages that already exist. Red links indicate Planner pages that have not yet been created. Middle-click or type @key{RET} on any link to view the link in the current window. Shift-middle-click or type @key{S-RET} to view the link in another window. @key{TAB} goes to the next link, while @key{S-TAB} goes to the previous one. You can pick up hyperlinks using the @code{planner-annotation-as-kill} function. @defun planner-annotation-as-kill Create a context-sensitive hyperlink for the current buffer and copy it to the kill ring. When called with a prefix argument, prompt for the link display name. @end defun You can then paste it into any Planner buffer by using @kbd{M-x yank} or the keyboard shortcut. Alternatively, you can create hyperlinks by typing them directly, using the syntax defined by Muse. Anything inside double square brackets will be treated as a link. For example, if you type @samp{[[GroceryList]]} in a Planner buffer, you will end up with a link to a page called @samp{GroceryList}. @inforef{Implicit Links, Bare URLs WikiNames and InterWiki links, muse}, for more information about Muse syntax. Hyperlinks are a powerful feature of Planner. You can use them to hyperlink to mail, news, Web pages, and even IRC connections. See the section on @ref{Managing Your Information} to find out how to enable support for various parts of Emacs. Want to add a new hyperlink scheme? Check out the source code for examples or ask on the mailing list for help. @node Example Page, Review, Hyperlinks, Getting Started @comment node-name, next, previous, up @section Example Page @cindex example page @cindex planning page, example An example planner file is given below. You'll notice that Planner does not have a well-defined user interface. Rather, it's free-form and open, allowing you to adapt it to your preferences. @example ---------------------------------------------------------------------- * Tasks #B _ Join http://mail.gna.org/listinfo/planner-el-discuss/ (TaskPool) #B _ Browse through the Planner info manual (TaskPool) #B _ Add (plan) to the end of my ~/.emacs #B X Learn how to schedule a task (TaskPool) * Schedule 18:00 | 19:00 | Learn how to use Planner * Notes Notes are free-form. You can put anything you want into this. .#1 This is note number one Notes on note number one! .#2 This weird ".#2" syntax is used for allout.el enumerated lists It makes using allout-mode very handy. @end example @node Review, , Example Page, Getting Started @comment node-name, next, previous, up @section Review @itemize @item @emph{Ideas for using planner more effectively:} @itemize @item Add @code{(plan)} to the end of your @file{~/.emacs} so that you are reminded about your tasks every day. @item Bind useful functions to shortcut keys and get used to creating tasks and notes from anywhere. @item Think about how you plan your day and look for ways to improve it. Ask the mailing list (@pxref{Getting Help}) for tips. @item Browse the rest of this manual, the source code, and other resources on the Net for tidbits you can use. @item Have fun! @end itemize @item @emph{Useful functions outside planner buffers:} @itemize @item @code{planner-create-task-from-buffer} @item @code{remember} @item @code{planner-goto-today} @item @code{planner-goto} @item @code{plan} @end itemize @item @emph{Useful functions inside planner buffers:} @itemize @item @kbd{C-c C-t} (@code{planner-create-task-from-buffer}) @item @kbd{C-c C-x} (@code{planner-task-done}) @item @kbd{M-x planner-edit-task-description} @item @kbd{C-c C-c} (@code{planner-copy-or-move-task}), @kbd{M-x planner-copy-or-move-region} @item @kbd{M-x planner-replan-task} @item @kbd{M-x planner-delete-task} @item @key{M-p} (@code{planner-raise-task}) and @key{M-n} (@code{planner-lower-task}) @item @key{C-M-p} (@code{planner-raise-task-priority}) and @key{C-M-n} (@code{planner-lower-task-priority}), @item @code{planner-replan-note} @item @code{planner-update-note} @end itemize @end itemize That's all you need to know in order to use Planner as a basic TODO and notes manager, but there's a whole lot more. Read through this manual and our mailing list archives (@pxref{Getting Help}) for lots of wonderful ideas about planning in Emacs! @node More about Planner, Managing Your Information, Getting Started, Top @comment node-name, next, previous, up @chapter More about Planner @menu * Navigation:: * More about Tasks:: * More about Notes:: * Making Files Pretty:: * Annotations:: * Interactive Lisp:: planner-lisp.el * Publishing:: planner-publish.el * Experimental Functions:: planner-experimental.el @end menu @node Navigation, More about Tasks, More about Planner, More about Planner @comment node-name, next, previous, up @section Starting with Day Pages @command{planner-goto-today} opens today's page. Day pages are named @samp{YYYY.MM.DD} and contain your notes for the day. They can also be named @samp{YYYY-MM-DD} if you prefer -- just customize the value of @var{planner-date-separator}. You should see a file that looks like this: @example * Tasks * Schedule * Notes @end example You can type anything you want into this file. You can add or delete sections. Use the following commands to navigate through day pages: @defun plan Start planning the day. If @code{planner-carry-tasks-forward} is non-nil, copy the most recent unfinished tasks to today's page, else open the most recent page. @end defun @defun planner-goto (@kbd{C-c C-j C-d}) Prompt for a date using a calendar pop-up and display the corresponding day page. You can specify dates partially. The current year and month are used if omitted from the input. For example, if today is 2004.05.05, then @itemize @item @kbd{+1} is one day from now, or @samp{2004.05.06} @item @kbd{-1} is one day before now, or @samp{2004.05.04} @item @kbd{12} is equivalent to @samp{2004.05.12} @item @kbd{8.12} is equivalent to @samp{2004.08.12} @item @kbd{2005.08.12} is a full date specification @end itemize In the calendar buffer, you can also left-click or press @key{RET} on a date to select it. @end defun @defun planner-goto-today (@kbd{C-c C-j C-j}) Display today's page. Create the page if it does not yet exist. @end defun @defun planner-goto-tomorrow (@kbd{C-c C-j C-t}) Goto the planner page days @var{after} the currently displayed date. If @var{days} is nil, go to the day immediately after the currently displayed date. If the current buffer is not a daily planner page, calculate date based on today. @end defun @defun planner-goto-yesterday (@kbd{C-c C-j C-y}) Goto the planner page @var{days} before the currently displayed date. If @var{days} is nil, go to the day immediately before the currently displayed date. If the current buffer is not a daily planner page, calculate date based on today. @end defun @defun planner-goto-most-recent Go to the most recent day with planning info. @end defun @defun planner-goto-previous-daily-page Goto the last plan page before the current date. The current date is taken from the day page in the current buffer, or today if the current buffer is not a planner page. Do not create pages if they do not yet exist. @end defun @defun planner-goto-next-daily-page Goto the first plan page after the current date. The current date is taken from the day page in the current buffer, or today if the current buffer is not a planner page. Do not create pages if they do not yet exist. @end defun @defun planner-goto-plan-page page Opens @var{page} in the the @code{planner-project} Wiki. Use @code{planner-goto} if you want fancy calendar completion. @end defun @defun planner-show date Show the plan page for @var{date} in another window, but don't select it. If no page for @var{date} exists, return nil. @end defun @node More about Tasks, More about Notes, Navigation, More about Planner @comment node-name, next, previous, up @section More about Tasks @cindex tasks, more about This section is divided into three parts. In the first part, you can read about all the options, strategies and commands to help you efficiently add new tasks to your planner. In the second part, we'll go over all of the aspects of Planner that relate to organizing, editing, rescheduling and viewing the tasks you've already created. Finally, we'll cover some ways to step back and look at various reports and overviews that can be generated from your planner pages. You may also be interested in tracking time spent on tasks with @ref{Timeclock} and estimating project completion time with @ref{Schedule} (also see @pxref{schedule.el}). @menu * Creating New Tasks:: * Organizing Your Tasks:: * Task Reports and Overviews:: @end menu @node Creating New Tasks, Organizing Your Tasks, More about Tasks, More about Tasks @comment node-name, next, previous, up @subsection Creating New Tasks @cindex tasks, creating Planner makes it very easy to quickly add something to your list of tasks. Once you get used to the basics of @command{planner-create-task-from-buffer}, you might want to take a closer look at some things in Planner that can help you create new tasks in a way that fits with your system. @menu * Creating a Task:: * Task Priorities:: * Task IDs:: planner-id.el * Cyclic Tasks:: planner-cyclic.el * Task Detail:: * Deadlines:: planner-deadline.el @end menu @node Creating a Task, Task Priorities, Creating New Tasks, Creating New Tasks @comment node-name, next, previous, up @subsubsection Creating a Task @cindex tasks, creating You can create a task from any buffer in Emacs by invoking @command{M-x planner-create-task-from-buffer}. This command does more than just add an item to your list of tasks. It also connects that item to some useful context information. If you create a task while viewing any buffer other than a Planner day page, Planner will associate the task with a hyperlink to that buffer. Try it now by creating a task from this Info buffer. @enumerate @item @kbd{M-x planner-create-task-from-buffer} @item When prompted for the task name, enter @kbd{Learn how to change a task's status} and press @key{RET}. @item When prompted for the date, press @key{RET} to schedule the task for today. @item When prompted for the project page, press @key{RET} to accept the default page of @samp{TaskPool}. This is a page for tasks not connected to a larger plan. @end enumerate Planner prompts you for two pieces of information when you ask it to create a task. First, it asks you when you would like to have the task show up in your planner. If you would like it to be scheduled for today, you can just hit @key{RET}. If you would like it to be scheduled for some day during the current month, you can just enter the date, without the month, like @samp{16}. If you would like it to be scheduled for some day in a future month of the current year, you can enter just the month and date, like @samp{06.16}. If you would like to schedule something for next year, then enter the full date, like @samp{06.16.2005}. If you do not want this task to appear on a day page at all, you can enter @samp{nil}. The second piece of information Planner asks for is the name of the project to associate the task with. In the above example, you associated the task with the project ``TaskPool'', which means that you did not want to associate the task with a particular project or goal in your life. Another way to do this is to answer the project prompt by entering @samp{nil}. But instead, you might enter @samp{LearnPlanner} as the project. This creates a new page called ``LearnPlanner'' in your planner directory and places an entry for the task on that page. The task then exists in two places: once on your day page, to show how it fits into your daily work; and once on a project page, to show how it fits into your larger projects and goals. In the future you might add related tasks like, ``Memorize Planner keybindings''. These tasks might be scattered over weeks or months worth of day pages, but as long as you enter the same project name for each, you will have a way to look at them all together on a single project page. Planner also creates hyperlinks to enable you to easily move back and forth between the day page system and the project page system. Each task on a day page will have a hyperlink to its project page. Each task on a project page will have a hyperlink to its day page. After using Planner for a while, you may find yourself with quite a few project pages. Keep in mind that completion is enabled at the project prompt when you create a task, so hitting @kbd{SPC} or @kbd{TAB} at the prompt will show you a list of your current project pages. Once the task is created, you are returned to the buffer you were working in again, Planner gets out of your way, and you can go on about your business. Later on, when you decide to actually work on that ``Memorize Planner keybindings'' task, you will be able to follow the hyperlink from that task on your day or project page directly to the relevant node in the Planner info file! By default, @command{M-x planner-create-task-from-buffer} creates medium-priority tasks, marked with the letter @samp{B}. But you can specify a particular priority or change the default (@pxref{Task Priorities}). You don't have to use @command{planner-create-task-from-buffer} to create tasks. You can also create new tasks manually by typing them directly on your day or project page in the format Planner expects. You can even still create hyperlinks by using Muse formatting as you manually type the new task (@pxref{Hyperlinks}). Keep in mind also that tasks do not have to be linked to any other page. For convenience, @command{planner-create-task-from-buffer} is bound to @kbd{C-c C-t} in Planner buffers. You can bind @command{planner-create-task-buffer} to a shortcut key. See the manual for your Emacs distribution to find out more about keybinding. @defun planner-create-task-from-buffer title date plan-page Create a new task named @var{title} on @var{date} based on the current buffer. With a prefix, associate the task with the current planner page. If you create a task on a date page, you will be prompted for a plan page. If you create a task on a plan page, you will be prompted for a day page. If nil is specified, the task is created only on the current page. See @code{planner-create-task} for more information. The new task is created at the top or bottom of the first block of tasks on the scheduled day page (if any), depending on the value of @code{planner-add-task-at-end-flag}. @end defun @defun planner-create-task title date annotation plan-page Create a new task named @var{title} based on the current Wiki page. If @var{date} is non-nil, makes a daily entry on @var{date}, else makes an entry in today's planner page. It's assumed that the current Wiki page is the page you're using to plan an activity. Any time accrued to this task will be applied to that page's name in the timelog file, assuming you use timeclock (@pxref{Time Intervals, , , Emacs, GNU Emacs Manual}). If @var{annotation} is non-nil, it will be used for the page annotation. If @var{plan-page} is non-nil, the task is associated with the given page. With a prefix, associate the task with the current planner page. If you create a task on a date page, you will be prompted for a plan page. If you create a task on a plan page, you will be prompted for a day page. If nil is specified, the task is created only on the current page. You probably want to call @code{planner-create-task-from-buffer} instead. The new task is created at the top or bottom of the first block of tasks on the scheduled day page (if any), depending on the value of @code{planner-add-task-at-end-flag}. @end defun @node Task Priorities, Task IDs, Creating a Task, Creating New Tasks @comment node-name, next, previous, up @subsubsection Task Priorities You can set the priority of a task when you create it, rather than waiting to adjust it after the fact. In order to do this, call the function corresponding to the priority you want. You probably want to bind these functions to some keys if you intend to use them much. @itemize @item @code{planner-create-high-priority-task-from-buffer} creates a task with priority @samp{A}. @item @code{planner-create-medium-priority-task-from-buffer} creates a task with priority @samp{B}. @item @code{planner-create-low-priority-task-from-buffer} creates a task with priority @samp{C}. @end itemize Or, you can change the default priority of @command{planner-create-task-from-buffer} by customizing @var{planner-default-task-priority}. You can actually use just one general priority, but using more than one color-codes your tasks and gives you a better overview of your day. @node Task IDs, Cyclic Tasks, Task Priorities, Creating New Tasks @comment node-name, next, previous, up @subsubsection Task IDs @cindex @file{planner-id.el}, using @cindex tasks, IDs After loading @file{planner.el}, make sure that @file{planner-id.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-id) @end example This module modifies the behavior of @file{planner.el}, adding global task IDs so that tasks can be edited and updated. Planner IDs are of the form @samp{@{@{Identifier:Number@}@}}. @subheading Options @defopt planner-id-add-task-id-flag Non-nil means automatically add global task IDs to newly-created tasks. If nil, use @command{planner-id-add-task-id} to add IDs to existing tasks, or @command{planner-id-add-task-id-to-all} to add to all tasks on the current page. @end defopt @defopt planner-id-update-automatically Non-nil means automatically update linked tasks whenever a page is saved. If nil, use @command{planner-update-task} to update the linked task. By default, linked tasks are automatically updated. @end defopt @defopt planner-id-tracking-file File that contains ID tracking data. This file is automatically overwritten. @end defopt @subheading Functions The following interactive functions are defined in @file{planner-id.el}: @defun planner-id-jump-to-linked-task &optional info Display the linked task page. If @var{info} is specified, follow that task instead. @end defun @defun planner-id-add-task Add a task ID for the current task if it does not have one yet. Update the linked task page, if any. @end defun @defun planner-id-update-tasks-on-page &optional force Update all tasks on this page. Completed or cancelled tasks are not updated. This can be added to @code{write-file-functions}. If @var{force} is non-nil, completed and cancelled tasks are also updated. @end defun @defun planner-id-add-task-id-to-all Add a task ID for all the tasks on the page. Update the linked page, if any. @end defun @defun planner-id-search-id id Search for all occurrences of @var{id}. @end defun @defun planner-id-follow-id-at-point Display a list of all pages containing the ID at point. @end defun @defun planner-id-follow-id-at-mouse event Display a list of all pages containing the ID at mouse. @var{event} is the mouse event. @end defun @node Cyclic Tasks, Task Detail, Task IDs, Creating New Tasks @comment node-name, next, previous, up @subsubsection Cyclic Tasks @cindex @file{planner-cyclic.el}, using @cindex tasks, cyclic @cindex cyclic tasks @cindex recurring tasks If there are tasks that you have to do regularly, you can have Planner schedule those tasks automatically. Make sure that @file{planner-cyclic.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-cyclic) @end example Create a diary file named @file{~/.diary.cyclic-tasks} (or the value of @code{planner-cyclic-diary-file}). Here is an example: @example Tuesday #B0 _ Study Japanese Friday #B0 _ Study Japanese (JapaneseStudies) @end example The first will be a plain task, the second will be linked. The first line will automatically create its task every Tuesday, while the second will create it every Friday. You can schedule tasks in a variety of ways. This module uses the same syntax for specifying when tasks will be scheduled as the Emacs diary uses for appointments and events. See @xref{Date Formats,, Date Formats, emacs, the GNU Emacs Manual}, and @xref{Sexp Diary Entries,, Sexp Entries and the Fancy Diary Display, emacs, the GNU Emacs Manual}, for a full description of the possibilities. By default, planner-cyclic creates multiple tasks if you let tasks build up (that is, the next Tuesday rolls around and you @emph{still} haven't marked the task as done.) To turn off this behavior: @example (setq planner-cyclic-diary-nag nil) @end example @subheading Functions @file{planner-cyclic-diary} includes the following interactive functions: @defun planner-cyclic-create-tasks-maybe Maybe create cyclic tasks. This will only create tasks for future dates or today. @end defun @node Task Detail, Deadlines, Cyclic Tasks, Creating New Tasks @comment node-name, next, previous, up @subsubsection Task Detail @cindex tasks You may find your planner pages getting very full, so that you want to have one broad task entry be linked to a more specific list of sub-tasks. Or, maybe you want to have a number of notes linked to a particular task. @cindex tasks, sub- @cindex tasks, meta- @cindex meta-tasks @cindex sub-tasks This can be done with targets. You can have a task that is really a meta-task: @example #A1 _ Do things in RevelleLog#13 @{@{Tasks:101@}@} (RevelleLog) @end example @samp{RevelleLog#13} could then be a list of sub-tasks in the form of a note, or any kind of note. Or, instead of pointing to a particular note on @samp{RevelleLog}, you could have the whole page be tasks that you enter in manually, without linking them to another page. You can just type them in like this: @example #A1 _ First specific thing to do @end example This way, the tasks will only appear on this specific project page, and not on any daily page, so you only see them when you want to look up all of the specific tasks associated with @samp{#A1 _ Do things in RevelleLog @{@{Tasks:101@}@} (RevelleLog)}. As you can see, the ability to manually enter tasks is one of Planner's nicest features. It allows you to create tasks that are not assigned to a specific date (by manually entering them on a project page with no date) or to a specific project (by manually entering them on a day page with no project). Yet as long as you enter them using the syntax it understands, Planner will continue to recognize them as tasks. Another way to have a task not be connected to a particular date is to do @kbd{C-c C-c} (@code{planner-copy-or-move-task}) and specify @samp{nil} when asked for the date. If you would like to see a list of all of your unfinished scheduled tasks, do @kbd{M-x planner-list-unfinished-tasks}. It is only intended to give you an overview. Any editing you want to do, like marking tasks complete or editing their description, still needs to be done on one of the tasks' ``real'' planner pages. @node Deadlines, , Task Detail, Creating New Tasks @comment node-name, next, previous, up @subsubsection Deadlines @cindex tasks, deadlines for @cindex deadlines, task @cindex @file{planner-deadline.el}, using You can use @file{planner-deadline.el} to automatically recalculate days to a deadline by adding @code{(require 'planner-deadline)} to your @file{~/.emacs}. With the default setup, make your tasks of the form @example #A0 _ Some task @{@{Deadline: 2004.09.12@}@} @end example (Note: There must be at least one space after the colon.) After you run @code{planner-deadline-update} to update task descriptions, the task will be of the form @example #A0 _ Some task @{@{Deadline: 2004.09.12 - 2 days@}@} @end example @subheading Options @defopt planner-deadline-regexp Regular expression for deadline data. The special deadline string should be regexp group 1. The date (YYYY.MM.DD) should be regexp group 2. @end defopt @subheading Functions @defun planner-deadline-update Replace the text for all tasks with deadlines. Deadlines are of the form @samp{@{@{Deadline: YYYY.MM.DD@}@}} by default. @end defun @defun planner-deadline-change &optional date Change the deadline of current task to @var{date}. If @var{date} is nil, remove deadline. @end defun @node Organizing Your Tasks, Task Reports and Overviews, Creating New Tasks, More about Tasks @comment node-name, next, previous, up @subsection Organizing Your Tasks @cindex tasks, organizing @cindex tasks, old Okay, now that you've gotten the hang of creating tasks, you're probably facing a really long list of things to do. How can you organize them so that they don't overwhelm you? Planner gives you a number of strategies for dealing with large numbers of tasks. @enumerate @item Arrange your tasks in the rough order you're going to do them. @item Use #A, #B and #C task priorities to differentiate between high-priority, normal and low-priority tasks. @item Schedule your tasks onto different days. @item Group your tasks into plan pages. @item Don't schedule all your tasks. @end enumerate @enumerate @item @emph{Task order} To remind yourself to do tasks in a certain order, simply edit the lines so that they're in the order you want. You can use normal editing commands like kill, yank and transpose-line to reorder the tasks, or use @key{M-p} (@code{planner-raise-task}) and @key{M-n} (@code{planner-lower-task}) to rearrange the tasks. @item @emph{Task priorities} By default, tasks are created with medium priority (@samp{#B}). You can make a task high-priority (@samp{#A}) or low-priority (@samp{#C}) by manually editing the task and calling M-x planner-update-task to update the linked page. Alternatively, you can use @key{C-M-p} (@code{planner-raise-task-priority}) and @key{C-M-n} (@code{planner-lower-task-priority}) to modify the task and update the linked page. You can edit the priority of a task using @kbd{M-x planner-edit-task-priority}, or manually edit it and call @kbd{M-x planner-update-task} to update tasks on the linked page. @item @emph{Schedule your tasks on different days} You don't have to do everything today. Is this a task you would rather do tomorrow? Schedule it for then instead. You can specify @samp{+n} or @samp{-n} whenever you are asked for a date, where @var{n} is the number of days before or after the current file's date or today. Don't over-procrastinate things, though! @item @emph{Plan pages} Plan pages let you group related tasks and notes together for easy reference. For example, you could have a plan page for each major project or goal in your life, like @samp{GoodHealth} or @samp{FurtherStudies}. Although plan pages start by grouping everything under a @samp{* Tasks} header, you can organize your plan pages in different ways. For example, you can separate groups of tasks with blank lines, and Planner will sort tasks within each group. @item @emph{Tasks without dates} Plan pages also allow you to have undated tasks or tasks with no particular deadlines. This keeps your daily task list small and manageable while making it easier for you to find things to do if you have free time. Make sure you check your plan pages regularly so that you don't completely forget about them. For automated scheduling of the next task on a plan page after you complete a task, see the section in @uref{http://sacha.free.net.ph/notebook/emacs/planner-config.el} named ``Schedule next undated task from same project''. @end enumerate @menu * Multiple Projects:: * Viewing Tasks:: * Modifying Tasks:: * Carrying Over Unfinished Tasks:: * Task Numbering:: * Task Ranks:: planner-rank.el * Grouping Tasks:: planner-trunk.el @end menu @node Multiple Projects, Viewing Tasks, Organizing Your Tasks, Organizing Your Tasks @comment node-name, next, previous, up @subsubsection Associating Tasks with Multiple Projects @cindex multiple projects @cindex @file{planner-multi.el}, using You can use @file{planner-multi.el} to associate a task with more than one project. That way, you can easily keep GTD-style context lists as well as project-related lists. To use multiple projects, add the following to your @samp{~/.emacs}: @example (require 'planner-multi) @end example Under GNU Emacs, you can specify multiple projects by separating them with a single space. For example, you can specify @kbd{planner doc} when creating a task to associate the task with those two projects. Under XEmacs, you can specify multiple projects by typing @kbd{RET} after each entry and terminating the list with another @kbd{RET}. For example, to specify @kbd{planner} and @kbd{doc}, you would type @kbd{planner RET doc RET RET} at the prompt. If you want to see an overview of all of your tasks as well as project- or context-specific lists, you can set @code{planner-multi-copy-tasks-to-page} to your overview page(s). For example, set it to @samp{TaskPool} to be able to see an overview of all of your unfinished tasks. You can also set this to multiple pages such as @samp{[[TasksByProject][p]] [[TasksByContext][c]]} and use @file{planner-trunk.el} to sort and organize tasks for easy reference. (@pxref{Grouping Tasks}) @subheading Options @defopt planner-multi-copy-tasks-to-page Automatically copy newly-created tasks to the specified page. @end defopt By default, tasks are removed from @code{planner-multi-copy-tasks-to-page} when you call @code{planner-task-done} or @code{planner-task-cancelled}. If you prefer to keep a copy of the task, remove @code{planner-multi-remove-task-from-pool} from @code{planner-mark-task-hook}. If you want to use a different separator instead of spaces, customize the @code{planner-multi-separator} variable. @defopt planner-multi-separator String that separates multiple page references. For best results, this should be something recognized by @code{muse-link-at-point} so that links are highlighted separately. @end defopt @node Viewing Tasks, Modifying Tasks, Multiple Projects, Organizing Your Tasks @comment node-name, next, previous, up @subsubsection Viewing tasks @cindex tasks, viewing Review the tasks scheduled for today by typing @kbd{M-x planner-goto-today}. If you created the task from the previous section in this tutorial, you should see a line that looks like @example #A _ Learn how to change a task's status from Tasks (TaskPool) @end example If you have @code{planner-use-task-numbers} set to non-nil, you will see something like the following instead. @example #A0 _ Learn how to change a task's status from Tasks (TaskPool) @end example From left to right, these are what the symbols mean: @itemize @item @samp{A} - Priority. A (high) @item @samp{0} - Priority number. It is calculated whenever you save the file or call @command{planner-renumber-tasks}, provided that @code{planner-use-task-numbers} is non-nil. Tasks are numbered in ascending order according to priorities. @item @samp{_} - Status. _ (unfinished) @end itemize If you click on @samp{Tasks} or press @key{RET} while your cursor is in the link, Emacs will display the previous info page. If you select @samp{TaskPool}, Emacs will display the @samp{TaskPool} plan page. Plan pages organize your tasks and notes about a project in one file. @subheading Functions You can use @command{planner-seek-next-unfinished-task} to move to the next unfinished task on the current page. @defun planner-list-tasks-with-status status &optional pages Display all tasks that match the STATUS regular expression on all day pages. The PAGES argument limits the pages to be checked in this manner: @itemize @item @code{t}: check all pages @item regexp: search all pages whose filenames match the regexp @item list of page names: limit to those pages @item alist of page/filenames: limit to those pages @end itemize Called interactively, this function will search day pages by default. You can specify the start and end dates or leave them as nil to search all days. Calling this function with an interactive prefix will prompt for a regular expression to limit pages. Specify @samp{.} or leave this blank to include all pages. This function could take a long time. @end defun @defun planner-list-unfinished-tasks &optional pages Display all unfinished tasks. @var{pages} follows planner-list-tasks-with-status. @end defun @defun planner-jump-to-linked-task task-info Display the task page linked to by the current task or @var{task-info}. @end defun @node Modifying Tasks, Carrying Over Unfinished Tasks, Viewing Tasks, Organizing Your Tasks @comment node-name, next, previous, up @subsubsection Modifying Tasks @cindex tasks, modifying @cindex tasks, editing To select a task, move your cursor to the line containing the task. Change a task's priority (@samp{A}, @samp{B} or @samp{C}) by editing the line. @samp{#A} tasks are important. @samp{#B} are medium priority. @samp{#C} are low priority. Whenever you save the file or call @kbd{M-x planner-fix-tasks}, tasks are sorted and numbered according to priority and status. Change a task's status by calling one of the following functions: @itemize @item planner-task-in-progress @samp{o} (@kbd{C-c C-z}) @item planner-task-done @samp{X} (@kbd{C-c C-x}) @item planner-task-cancelled @samp{C} (@kbd{C-c C-S-x}) @item planner-task-delegated @samp{D} @item planner-task-pending @samp{P} @item planner-task-open @samp{_} @end itemize After changing the status using a function, look at the @samp{TaskPool} plan page. The task is also updated on the linked page. If you changed the task status manually by replacing the status with another character, you will need to call @command{planner-update-task} to update the linked page. To reschedule a task, call @command{planner-copy-or-move-task} (@kbd{C-c C-c}) and choose a new date. You can mark a region and type @kbd{M-x planner-copy-or-move-region} to reschedule all the contained tasks to a different date. Enter @samp{nil} for the date if you don't want the task or group of tasks to appear on any date page at all anymore. This is a good way to ``de-schedule'' a task for the time being, but still keep it linked to a plan page for possible future scheduling. To change the plan page associated with a task, call @command{planner-replan-task}. Enter @samp{nil} for the plan page if you don't want the task to appear on any plan page anymore. If you precede the command with a prefix argument, the text of the original plan page will appear in the prompt for easy editing. Since the same task may exist on two or more pages, such as a date page and a plan page, it is dangerous to edit the description of the task by hand. You should not do it unless you want to make the exact same changes on all its linked pages. Instead of doing this by hand, you should use @command{planner-edit-task-description}. This will prompt you for the changes to the task description and then update all the other pages to which the task is linked. Or, you can just use @command{planner-delete-task} to remove the task from both pages, and then create it again with the new desired description. To remind yourself to do tasks in a certain order, simply edit the lines so that they're in the order you want. @command{planner-raise-task} and @command{planner-lower-task} update the priorities on linked pages automatically. You can organize tasks into groups by putting a blank line between groups of tasks. Planner will maintain the groupings and only sort the tasks within that group. @subheading Functions @defun planner-replan-task page-name Change or assign the plan page for the current task. @var{page-name} is the new plan page for the task. Use @code{planner-copy-or-move-task} if you want to change the date. With a prefix, provide the current link text for editing. @end defun @defun planner-raise-task-priority Change a low-priority task to a medium-priority task and a medium-priority task to a high-priority task (C to B to A). @end defun @defun planner-lower-task-priority Change a high-priority task to a medium-priority task and a medium-priority task to a low-priority task (A to B to C). @end defun @defun planner-raise-task arg Move a task up @var{arg} steps. By default, @var{arg} is 1. @end defun @defun planner-lower-task arg Move a task down @var{arg} steps. By default, @var{arg} is 1. @end defun @defun planner-edit-task-description description Change the description of the current task, updating the linked page if any. @end defun @defun planner-delete-task Delete this task from the current page and the linked page. @end defun @defun planner-update-task Update the current task's priority and status on the linked page. Tasks are considered the same if they have the same description. This function allows you to force a task to be recreated if it disappeared from the associated page. Note that the text of the task must not change. If you want to be able to update the task description, see @code{planner-edit-task-description} or @file{planner-id.el}. @end defun See @command{planner-install-extra-task-keybindings} for additional task-related shortcuts. @node Carrying Over Unfinished Tasks, Task Numbering, Modifying Tasks, Organizing Your Tasks @comment node-name, next, previous, up @subsubsection Carrying Over Unfinished Tasks @cindex tasks, carrying over Sometimes you won't be able to cross off all the tasks on your list. Planner makes it easy for you to keep track of things you still have to do by automatically rescheduling unfinished tasks from the past few days. By default, the @command{plan} command searches for unfinished tasks from the last three days and reschedules them onto today. If you open Planner every day, this should cover weekends easily. It's a good idea to start Planner whenever you start Emacs. That way, Planner can help remind you about today's tasks, appointments, and other things. To automatically start Planner whenever you start up Emacs, add the following code to the end of your @file{~/.emacs}: @example (plan) @end example Now, every time you start Emacs (which should be more or less once a day), you'll see today's page. If you don't finish all the tasks today, you'll see them again tomorrow. It's a good idea to start Planner every time you start Emacs so that you get reminded about your task list. If you prefer to start Planner manually, remember to call @kbd{M-x plan} every so often to make sure that you don't forget any unfinished tasks. Safe in the knowledge that Planner tasks won't slip through the cracks (unlike little slips of paper that will invariably get mislaid), you can then get on with the rest of your life. If your increased productivity with Planner leads to a well-deserved two-week vacation, then you'll need to tell Planner to search more days for unfinished tasks. By using @kbd{M-x plan}, you can automatically bring forward tasks over a given number of days or even scan all the days since time immemorial. @kbd{C-u 15 M-x plan} reschedules all unfinished tasks from the last 15 days. @kbd{C-u -1 M-x plan} checks all of your past day pages for unfinished tasks. Like everything else in Planner, you can adapt @kbd{M-x plan} to your particular way of life. For example, if you find yourself starting up Emacs and Planner every day--including weekends--because it's just so much fun, you can set the @code{planner-carry-tasks-forward} to 1. This can make your Emacs startup marginally faster. On the other hand, if you normally start Emacs once a week, you can set it to 7 or 8. If you're worried about tasks dropping off your radar, you can set it to 0. You can set the value of @var{planner-carry-tasks-forward} either with @key{M-x customize-variable RET planner-carry-tasks-forward RET}, or by putting @code{(setq planner-carry-tasks-forward 3)} (replacing @code{3} with the value appropriate for what you want) in your @file{~/.emacs} file. On the other hand, you might prefer to reschedule tasks yourself. If you set @code{planner-carry-tasks-forward} to @code{nil}, then @command{M-x plan} and @code{(plan)} will bring you to the most recent page with unfinished tasks if there is no page for today. You can then use @command{planner-copy-or-move-task} and @command{planner-copy-or-move-region} to reschedule tasks. This is probably more hassle than it's worth, though, so let Planner take care of this for you. @subheading Options @defopt planner-carry-tasks-forward If non-nil, carry unfinished tasks forward automatically. If a positive integer, scan that number of days in the past. If 0, scan all days for unfinished tasks. If t, scan one day in the past (old behavior). If nil, do not carry unfinished tasks forward. @end defopt @subheading Functions @defun plan &optional force-days Start your planning for the day, carrying unfinished tasks forward. If @var{force-days} is a positive integer, search that many days in the past for unfinished tasks. If @var{force-days} is @code{0} or @code{t}, scan all days. If @var{force-days} is @code{nil}, use the value of @code{planner-carry-tasks-forward} instead, except t means scan only yesterday @end defun @defun planner-copy-or-move-task date force Reschedule the task for @var{date}. If @var{force} is non-nil, the task is moved regardless of status. It also works for creating tasks from a Note. Use @code{planner-replan-task} if you want to change the plan page in order to get better completion. @end defun @defun planner-copy-or-move-region beg end date muffle-errors Move all tasks from @var{beg} to @var{end} to @var{date}. @code{planner-copy-or-move-region} will copy or move all tasks from the line containing @var{beg} to the line just before @var{end}. If @var{muffle-errors} is non-nil, no errors will be reported. @end defun @node Task Numbering, Task Ranks, Carrying Over Unfinished Tasks, Organizing Your Tasks @comment node-name, next, previous, up @subsubsection Task Numbering By default, tasks are numbered according to their position on the page. Task numbers allow you to refer to tasks using Muse links. For example, the @samp{#A1} task in @file{2004.08.16} can be referred to as @samp{2004.08.16#A1}. Note that task numbers change every time you re-sort and re-number tasks with @code{planner-fix-tasks}. As a result, they are only reliable for references to past tasks. If you find yourself not using this functionality, you can turn off task numbers by using the following option. @subheading Options @defopt planner-use-task-numbers Non-nil means use task numbers when creating tasks. This allows you to refer to past tasks if your tasks are numbered appropriately. If you set this to nil, you can save space in your plan files. @end defopt @node Task Ranks, Grouping Tasks, Task Numbering, Organizing Your Tasks @comment node-name, next, previous, up @subsubsection Task Ranks @cindex ranking tasks @cindex tasks, ranking @cindex @file{planner-rank.el}, using @file{planner-rank.el} models Franklin Covey's Urgency and Importance principle. When you think about a task, there are two aspects in consideration: Urgency and Importance. You may want to do the most urgent things first, like answering an email, or you may want to do the most important things first, like reading this manual. Or much better, balance Urgency and Importance and decide what to do. @file{planner-rank.el} can help you balance. Urgency and Importance are both measured by scores from 0-9. The higher the score, the more you want to do it first. 9 stands for ``I should have done this'' and 0 stands for ``I can forget this''. If you are using the planner @ref{Deadlines} feature, the Urgency score is automatically calculated from how many days are left to meet the deadline. By default, it will score 9 if the task is overdue and 0 if the deadline is years away. Please refer to the docstring of @code{planner-rank-deadline-urgency-map-list} for detail. The task rank is calculated from Urgency and Importance scores. As different people balance urgency and importance differently, a number of @code{planner-rank-calculate-rank-*} functions are provided. The algorithms vary from a simple average to something like a weighted root mean square deviation. The aggressive versions of these functions (@code{planner-rank-calculate-rank-*-aggressive}) will make sure if one of Urgency and Importance is high, the resulting rank will be high as well. @code{planner-rank-calculate-rank-weighted-*} functions weigh the Urgency and Important scores depending on @code{planner-rank-importance-vs-urgency-factor}. Call @code{planner-rank-test-algorithm} on each of the functions and check the result tables to see which one you like most, and set it to @code{planner-rank-rank-calculate-function}. Alternatively, accept the defaults and tweak them when you get a better feel for ranking. Once the Rank is calculated, the @ref{Task Priorities} will be automatically reset. If the Rank is greater than or equal to @code{planner-rank-priority-A-valve}, the task priority will be @samp{A}, if the Rank is between @code{planner-rank-priority-A-valve} and @code{planner-rank-priority-B-valve}, the priority will be @samp{B}, else it will be @samp{C}. After setting the task importance and deadline, you can leave it as is. As the deadline approaches, the task priority will automatically be raised and the task re-colored to catch your eyes. If you are using @code{planner-sort-tasks} (see @pxref{Making Files Pretty}), you can set @code{planner-sort-tasks-key-function} to one of @code{planner-sort-tasks-by-rank}, @code{planner-sort-tasks-by-importance}, and @code{planner-sort-tasks-by-urgency}. @subheading Options @defopt planner-rank-change-hook Functions to run after @code{planner-rank-change}. @end defopt @defopt planner-rank-priority-A-valve Tasks with rank greater than or equal to this value will be set to priority @samp{A}. @end defopt @defopt planner-rank-priority-B-valve Tasks with rank greater than or equal to this value and less than @code{planner-rank-priority-A-valve} will be set to priority @samp{B}. Tasks with rank less than this value will be set to priority @samp{C}. @end defopt @defopt planner-rank-deadline-urgency-map-list Defines how to calculate the Urgency score according to how many days are left to meet the deadline. @end defopt @defopt planner-rank-default-importance Default importance value for newly added rank. @end defopt @defopt planner-rank-default-urgency Default urgency value for newly added rank. @end defopt @defopt planner-rank-importance-vs-urgency-factor How much do you think importance is more ``important'' than urgency. This will be used in @code{planner-rank-calculate-rank-weighted-*} functions. @end defopt @defopt planner-rank-rank-calculate-function Define the function called to calculate rank. @end defopt @subheading Functions @defun planner-rank-change &optional importance urgency Set the Importance and Urgency of the current task. @end defun @defun planner-rank-update-current-task Recalculate rank for the current task. @end defun @defun planner-rank-update-all Recalculate rank for all tasks in the current page @end defun @defun planner-rank-update-all Recalculate rank for all tasks in the current page @end defun @node Grouping Tasks, , Task Ranks, Organizing Your Tasks @comment node-name, next, previous, up @subsubsection Grouping Tasks with planner-trunk.el @cindex grouping tasks @cindex tasks, grouping @cindex @file{planner-trunk.el}, using @file{planner-trunk.el} helps you automatically group tasks according to a set of rules. It sorts and splits your tasks, adding a blank line between groups of tasks. For example, if today's page looks like this: @example * Tasks #B _ Buy milk (GroceryShopping) #B _ Learn how to use planner-trunk (PlannerMode) #B _ Buy a notebook (Bookstore) #B _ Buy cereal (GroceryShopping) #B _ Set up my own planner-trunk rules (PlannerMode) #B _ Customize my stylesheet (MuseMode) #B _ Go for a health checkup (BetterHealth) @end example @noindent then you might want to group the tasks into: planner and muse, shopping list, and other items. If you set up the appropriate rules by customizing @code{planner-trunk-rule-list}, @file{planner-trunk.el} can automatically rewrite that section line this: @example * Tasks #B _ Learn how to use planner-trunk (PlannerMode) #B _ Set up my own planner-trunk rules (PlannerMode) #B _ Customize my stylesheet (MuseMode) #B _ Buy milk (GroceryShopping) #B _ Buy a notebook (BookstoreShopping) #B _ Buy cereal (GroceryShopping) #B _ Go for a health checkup @end example @noindent In this case, you would set @code{planner-trunk-rule-list} to @code{(("." nil ("PlannerMode\\|MuseMode" "Shopping")))}. You can load @file{planner-trunk} with @kbd{M-x load-library RET planner-trunk RET} or add @code{(require 'planner-trunk)}. If you're not yet comfortable with Emacs Lisp, you can use @kbd{M-x customize-variable RET planner-trunk-rule-list RET} to edit this rule using an easy-to-use interface. WARNING: Do not keep non-task information in the Tasks section. planner-trunk will delete @strong{all} non-task lines from the Tasks section of your plan page in the process of grouping the tasks. After you set up @code{planner-trunk-rule-list}, use @command{M-x planner-trunk-tasks} to try out your rules until you're satistfied. If you want to do this automatically, you can use @code{(add-hook 'planner-mode-hook 'planner-trunk-tasks)} to trigger it automatically whenever you open a Planner page. @node Task Reports and Overviews, , Organizing Your Tasks, More about Tasks @subsection Task Reports and Overviews @cindex task reports @cindex task overviews @cindex reports, task @cindex overviews, task @cindex reports, accomplishment @cindex tasks, overview of Planner provides a number of different ways to generate different presentations of your tasks. @menu * Accomplishments:: planner-accomplishments.el * Status Reports:: planner-report.el * Task Overviews:: planner-tasks-overview.el * tag:: * planner-registry:: Keep track of annotations * planner-zoom:: View and navigate tasks by time period @end menu @node Accomplishments, Status Reports, Task Reports and Overviews, Task Reports and Overviews @comment node-name, next, previous, up @subsubsection Generating Daily Accomplishment Reports @cindex reports, accomplishment @cindex @file{planner-accomplishments.el}, using @cindex tasks, overview of @cindex task reports @cindex reports, task @cindex overviews, task @cindex task overviews You can use @file{planner-accomplishments.el} to get a summary of your task activity for a particular day. The report is grouped by status and plan (on day pages) or date (on plan pages). An example report follows: @example Link | Unfinished | In progress | Delegated | Completed | Total nil | 1 | 0 | 0 | 6 | 7 TaskPool | 1 | 1 | 0 | 3 | 5 Planner | 0 | 0 | 1 | 1 | 2 SchoolWork | 0 | 0 | 0 | 1 | 1 Total | 2 | 1 | 1 | 11 | 15 @end example This lets you see how you balance your time between your projects. @itemize There are currently two ways to use @file{planner-accomplishments.el}. @item Displaying a temporary buffer You can call @code{planner-accomplishments-show} to display a buffer containing the current page's accomplishment report. @item Rewriting sections of your planner Choose this approach if you want accomplishment reports to be in their own section and you would like them to be readable in your plain text files even outside Emacs. Caveat: The accomplishment section should already exist in your template and will be rewritten when updated. To use, set @code{planner-accomplishments-section} to the name of the section to rewrite (default: @samp{Accomplishments}). If you want rewriting to be automatically performed, call @code{planner-accomplishments-insinuate}. The accomplishments will be rewritten whenever you save a planner page. If you want rewriting to be manual, call @code{planner-accomplishments-update}. @end itemize @subheading Options @defopt planner-accomplishments-section Header for the accomplishments section in a plan page. Used by @code{planner-accomplishments-update}. @end defopt @defopt planner-accomplishments-status-display Alist of status-label maps also defining the order of display. Used by @code{planner-accomplishments-format-table}. @end defopt @subheading Functions @defun planner-accomplishments-insinuate () Automatically call @code{planner-accomplishments-update} when saving tasks in @code{planner-mode} buffers. @end defun @defun planner-accomplishments-update () Rewrite @code{planner-accomplishments-section} with a summary of tasks on this page. @end defun @defun planner-accomplishments-show () Display a buffer with the current page's accomplishment report. @end defun @node Status Reports, Task Overviews, Accomplishments, Task Reports and Overviews @comment node-name, next, previous, up @subsubsection Status Reports @cindex status reports @cindex reports, status @cindex @file{planner-report.el}, using @file{planner-report.el} creates a status report for a given timespan. The report itself is just another Planner page in your planner directory. Once generated, it contains tasks and notes culled from active project pages. Tasks are only shown if they are incomplete or were completed within the timespan. Notes are shown if they were created during the timespan. Tasks and notes are grouped together under a heading for their corresponding project. The idea is you have one of these status reports generated periodically (say, every couple of weeks). Perhaps you use cron to run them automatically and then mail you a reminder that they've been done. Then you can edit the page, adding verbiage where it is needed and removing irrelevant items. This editing process is as easy as editing any other Planner page. Finally, you can publish the page along with the rest of your planner using @kbd{M-x muse-project-publish}. If you use planner-authz.el, you can tell planner-report.el only to consult project pages that a given list of users (@var{planner-report-authz}) can access when generating the report. For example, if you're preparing a status report for your boss, add yourself and him to @var{planner-report-authz}. The resulting status report will only contain information the two of you are supposed to have access to, and the report itself will be similarly restricted. @subheading Getting started Add the following to your .emacs file: @example (require 'planner-report) @end example Then you can use the following command to generate a status report: @example M-x planner-report-generate @end example You will be prompted for a beginning and ending date, and then the status report will be generated. You can then edit it to your liking and publish it just like you would the rest of your planner. @subheading Options @defopt planner-report-authz List of users a status report should be restricted to. When status reports are generated, only planner pages accessible by these users will be consulted, and the resulting status report will be similarly restricted. @end defopt @defopt planner-report-pretty-print-plan-pages If non-nil, pretty print plan pages. If nil, leave page names as-is. This requires that @file{muse-wiki.el} be loaded to work properly. @end defopt @defopt planner-report-remove-task-numbers Remove task numbers when generating status reports. @end defopt @defopt planner-report-replace-note-numbers If non-nil, a string with which to replace note numbers when generating status reports. @end defopt @defopt planner-report-unfinished-offset If non-nil, the offset in days from the current date of unfinished tasks to include in the status report. If nil, include all unfinished tasks. @end defopt @subheading Functions @defun planner-report-generate begin end Generate a status report spanning a period from @var{begin} to @var{end}. @var{begin} and @var{end} are in the format YYYY.MM.DD. @end defun @node Task Overviews, tag, Status Reports, Task Reports and Overviews @comment node-name, next, previous, up @subsubsection Seeing an Overview of Tasks @cindex tasks, overview of @cindex task reports @cindex reports, task @cindex overviews, task @cindex task overviews @cindex @file{planner-tasks-overview.el}, using You can see a list of tasks with @file{planner-tasks-overview.el}. Seeing how you've scheduled tasks over the next few days can help you decide when to schedule another task. Table entries will be of the form @var{date} | @var{link} | @var{priority} @var{status} | @var{task-description} @subheading Functions To display the tasks between a set of day pages, use @defun planner-tasks-overview start end Display an overview of your tasks from @var{start} to @var{end}. If @var{start} is nil, start from the very first day page. If @var{end} is nil, include the very last day page. You can use @code{planner-expand-name} shortcuts here, like @kbd{+1} or @kbd{-1}. Pressing @key{RET} at the prompt will use today. Once in a @code{planner-tasks-overview} buffer, you can use the keyboard shortcut @key{o} to change the overview period. @end defun You can sort the task display with the following functions: @defun planner-tasks-overview-sort-by-date Sort the tasks by date. Keyboard shortcut: @key{1} @end defun @defun planner-tasks-overview-sort-by-plan Sort the tasks by associated plan page. Keyboard shortcut: @key{2} @end defun @defun planner-tasks-overview-sort-by-priority Sort the tasks by priority. Keyboard shortcut: @key{3} @end defun @defun planner-tasks-overview-sort-by-status Sort the tasks by status. Keyboard shortcut: @key{4} @end defun You can jump to linked tasks with @defun planner-tasks-overview-jump other-window Display the current task. If a prefix argument is supplied, show the task in another window. Keyboard shortcut: @key{j} @end defun @defun planner-tasks-overview-jump-other-window Display the current task in another window. Keyboard shortcut: @kbd{C-u j} @end defun You can view a summary of the tasks in your plan pages with @defun planner-tasks-overview-show-summary &optional file-list Count unscheduled, scheduled, and completed tasks for FILE-LIST. If called with an interactive prefix, prompt for the plan page(s) to display. Load @file{planner-multi.el} to be able to specify multiple pages. @end defun @subheading Keys @key{TAB}, @kbd{SHIFT-TAB} and @key{RET} navigate links in the usual fashion. @node tag, planner-registry, Task Overviews, Task Reports and Overviews @subsubsection tag @cindex tag @cindex task reports @cindex reports, task @cindex overviews, task @cindex task overviews @cindex tasks, overview of @samp{} is replaced by a report of tasks over all day pages in published pages (@pxref{Publishing}). @example All incomplete tasks All completed tasks All tasks @end example Warning: this function can be slow, as it checks all the day pages! @node planner-registry, planner-zoom , tag, Task Reports and Overviews @comment node-name, next, previous, up @section planner-registry @cindex @file{planner-registry.el}, using The @file{planner-registry} module provides a way to keep track of all the URLs in your projects, and to list them depending on the current buffer. The URLs are defined in @code{muse-url-protocols} module from Muse. If a URL has been created by @code{planner-create-task-from-buffer}, going to that buffer and calling @code{planner-registry-show} will show you where Planner put the URL. @subheading Getting started To begin using @file{planner-registry}, add the following to your Planner configuration file. @example (require 'planner-registry) (planner-registry-initialize) @end example You must put it after the place where Planner has been loaded in your configuration file. If you want the registry to be updated each time you save a Planner file, add the following to your Planner configuration. @example (planner-registry-insinuate) @end example If you don't want to update the registry each time a file is written, you can do it manually with @code{planner-registry-update}: it will update the registry for saved Planner/Muse buffers only. @file{planner-registry} does not define any keybindings by default. Its most useful interactive function is @code{planner-registry-show}. @subheading Example usage Say for example that you created a task from an e-mail. Go to that e-mail and call @code{planner-registry-show}: it will open a new buffer displaying the files (in a muse links format) where a link to this e-mail has been added. @subheading Options @file{planner-registry} defines the following options. @defopt planner-registry-file The file where @file{planner-registry} stores its URL registry. @end defopt @defopt planner-registry-min-keyword-size The minimum size for keywords. @end defopt @defopt planner-registry-max-keyword-size The maximum size for keywords. @end defopt @defopt planner-registry-max-number-of-keywords The maximum number of keywords. @end defopt @defopt planner-registry-ignore-keywords A list of keywords to ignore. @end defopt @defopt planner-registry-show-level Level used by the @code{planner-registry-show} function. 0 means that this function shows only exact matches. 1 means that this function also shows descriptive matches. 2 (or more) means that this function also shows fuzzy matches. @end defopt @node planner-zoom, , planner-registry, Task Reports and Overviews @comment node-name, next, previous, up @section planner-zoom @cindex @file{planner-zoom.el}, using @cindex view, weekly @cindex view, quarterly @cindex view, monthly @cindex view, yearly When assessing where you stand in relation to the tasks you have set out for yourself, you might want a way to survey those tasks in groups divided by time periods, like by the week or by the month. You could create all of these overview pages by hand, but if you like to have this kind of overview frequently, you might find manually creating such pages to be tedious and time consuming. @file{planner-zoom} is an optional module designed to make it easy to view your task information grouped by year, quarter, month, week or day. To install this module, just load it in your @file{.emacs} (or @file{_emacs}): @example (require 'planner-zoom) @end example This module will recognize planner pages named according to the following scheme: @table @asis @item year view @file{2006.Year} @item quarter view @file{2006.Quarter2} @item month view @file{2006.January} @item week view @file{2006.January.Week3} @item day view @file{2006.01.02} @end table @subheading Keybindings This module also adds key bindings that you can use when looking at a Planner page to easily jump between the different time-period views. @table @kbd @item S-up Move to the view corresponding to the time period one step larger than the current one. For example, it moves from the weekly view to the monthly view. It calls @code{planner-zoom-iup}. @item S-down Move to the view corresponding to the time period one step smaller than the current one. For example, it moves from the weekly view to the daily view. It calls @code{planner-zoom-idown}. @item S-left Stay in the same time-period view as the current one, but move one interval earlier. For example, it moves from @file{2006.January.Week3} to @file{2006.January.Week2}. It calls @code{planner-zoom-iprev}. @item S-right Stay in the same time-period view as the current one, but move one interval later. For example, it moves from @file{2006.January.Week3} to @file{2006.January.Week4}. It calls @code{planner-zoom-inext}. @end table @subheading Example usage Look at the page named @file{2006.January} and then hit @kbd{S-down} which will show @file{2006.January.Week1}. Then hit @kbd{S-left} and @kbd{S-right} to look at @file{2006.January.Week2}, @file{2006.January.Week3}, etc. @subheading Advanced tips and options You can use any prefix argument with @code{planner-zoom-iup} and @code{planner-zoom-idown} to have the new view display in a window other than the current one. This also works with a nonnumeric prefix argument and @code{planner-zoom-inext} or @code{planner-zoom-iprev}. For these two functions, a numeric prefix will specify the number of intervals to move. If you don't like the default patterns for naming the time-period view pages, you can change them by customizing @code{planner-zoom-regexps}. Some people believe weeks start with Sunday, and some believe they start with Monday. To accommodate both of these colliding worldviews, @code{planner-zoom-first-day-of-week} can be customized. Its default value is @samp{1}, which is Monday. If you would prefer Sunday, change it to @samp{0}. The month to which a week belongs is the month in which the first day of the week falls. @subheading Command reference @defun planner-zoom-iup name other-window Move to the next higher level in the hierarchy. With a prefix argument, show the desired page in the other window. @end defun @defun planner-zoom-idown name other-window Move to the next lower level in the hierarchy. If the current date is within the higher-level time range, zoom to the lower level time range that also contains today. Otherwise, just go to the first lower-level time range. With a prefix argument, show the desired page in the other window. @end defun @defun panner-zoom-inext name num other-window Move to the next time range at the same level in the hierarchy. With a numeric prefix argument, move by that number of time ranges. With a non-numeric prefix argument, show the desired page in the other window. @end defun @defun planner-zoom-iprev name num other-window Move to the previous time range at the same level in the hierarchy. With a numeric prefix argument, move by that number of time ranges. With a non-numeric prefix argument, show the desired page in the other window. @end defun @node More about Notes, Making Files Pretty, More about Tasks, More about Planner @section More about Notes @cindex notes, more about Planner by default organizes the notes on a planner page so that the most recent note is first. Each note is numbered, with the oldest note labeled @samp{.#1}. If you would like to reverse this behavior, look at @kbd{C-h v planner-reverse-chronological-notes}. Notes are associated with day pages, but can also be associated with plan pages when they are created. A linked note looks like this: @example .#1 Headline (LinkedNote#1) Text @end example You can jump to the linked note with @command{planner-jump-to-linked-note}. Deleting a note can be dangerous, as the notes are automatically numbered. Removing a note could break links in other pages. @subheading Functions @defun planner-create-note page Create a note to be remembered in @var{page} (today if @var{page} is nil). If @code{planner-reverse-chronological-notes} is non-nil, create the note at the beginning of the notes section; otherwise, add it to the end. Position point after the anchor. @end defun @defun planner-create-note-from-task Create a note based on the current task and update the current task to link to the note. @end defun @defun planner-renumber-notes Update note numbering. @end defun @defun planner-jump-to-linked-note note-info Display the note linked to by the current note or @var{note-info} if non-nil. @end defun @defun planner-search-notes regexp limit Return a buffer with all the notes returned by the query for @var{regexp}. If called with a prefix argument, prompt for @var{limit} and search days on or after @var{limit}. @end defun The following sections include instructions for displaying, manipulating, and navigating your notes efficiently. @menu * Using Allout Mode:: Quickly navigating your notes * :: Note headlines * :: Index of past notes * Note Indices:: planner-notes-index.el @end menu @node Using Allout Mode, , More about Notes, More about Notes @subsection Using Allout Mode @cindex Allout mode @cindex notes, navigating @cindex notes, formatting @cindex notes, displaying The format of the notes in Planner works well with Allout mode, which provides helpful commands for navigating and formatting outlines. You can, for example, hide the bodies of all the notes on a page so you can see just their headlines. You can also jump easily from headline to headline, skipping over the bodies in between. The commands for using Allout mode vary depending on which Emacs version you are using. In either case, type @kbd{M-x load-library @key{RET} allout @key{RET}} to start. If you are using Emacs 22 or later, type @kbd{M-x allout-mode @key{RET}}. If you are using an earlier version of Emacs, type @kbd{M-x outline-mode @key{RET}}. The exact commands then available to you differ depending on your Emacs version, but you can view the commands and their keybindings by typing @kbd{C-h m}. In Emacs 22 or later, they will start with @command{allout-}, while in previous versions, they will start with @command{outline-}. For more information about using Allout mode, see @kbd{C-h f allout-mode @key{RET}}. @node , , Using Allout Mode, More about Notes @subsection @samp{} is replaced by a list of note headlines when the page is published. For example, the notes tag in the following example will be replaced by the two headlines when published. (@pxref{Publishing}) @example * Notes .#1 This is a headline and this is body text .#2 This is another headline and this is more body text @end example @samp{} is useful if you want to provide a quick summary of blog entries at the top of your page. Just add it to your @code{planner-day-page-template}. @node , Note Indices, , More about Notes @subsection @samp{} is replaced by an index of note headlines. If @var{start} is specified, it lists notes starting from that date. If @var{directory} is specified, you can index notes in another planner directory. @example All the notes I've taken in 2004: @end example @node Note Indices, , , More about Notes @comment node-name, next, previous, up @subsection Note Indices @cindex @file{planner-notes-index.el}, using @cindex notes, indexing Make sure that @file{planner-notes-index.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-notes-index) @end example Then you can use tags of the form: @example @end example You can also use the following interactive functions: @code{planner-notes-index} @code{planner-notes-index-days} @code{planner-notes-index-weeks} @code{planner-notes-index-months} @code{planner-notes-index-years} (wow!) These work based on the current date (date of current buffer, or today). If a single page is specified, this page is scanned for headlines of the form: @example .#1 Headline @end example The results are presented as a bulleted list. If @var{from} and @var{to} are specified, all date pages between them (inclusive) are scanned. If @var{from} is omitted, it is assumed to be the earliest entry. If @var{to} is omitted, it is assumed to be the latest entry. If @var{recent} is specified, the list includes only that many recent headlines. and the results are presented as a bulleted list. To customize presentation, you can write a function that generates the appropriate @code{} tags. You can also use @code{planner-extract-note-headlines} in your own functions. @subheading Functions The following interactive functions are defined in @file{planner-notes-index.el}: @defun planner-notes-index &optional from to limit Display a clickable notes index. If called from a Lisp program, display only dates between @var{from} and @var{to}. With a prefix arg @var{limit}, display only that number of entries. @end defun @defun planner-notes-index-days days Display an index of notes posted over the past few @var{days}. The list ends with the day of the current buffer or @code{planner-today}. @end defun @defun planner-notes-index-weeks weeks Display an index of notes posted over the past few @var{weeks}. The list ends with the week of the current buffer or @code{planner-today}. Weeks start from Sunday. @end defun @defun planner-notes-index-months months Display an index of notes posted over the past few @var{months}. The list ends with the month of the current buffer or @code{planner-today}. @end defun @defun planner-notes-index-years years Display an index of notes posted over the past few @var{years}. The current year is included. @end defun @file{planner-notes-index.el} does not define any keybindings. @node Making Files Pretty, Annotations, More about Notes, More about Planner @section Making Files Pretty By default, planner does a little bit of fancy reformatting when you save a file. Tasks are sorted by priority (ABC) and status (_oP>XC) on day pages. On plan pages, tasks are sorted by priority (ABC), status (XC), and date. Undated tasks are sorted after dated tasks. @subheading Options @defopt planner-sort-tasks-key-function Control task sorting. Some options include @code{planner-sort-tasks-default-key}, @code{planner-sort-tasks-basic}, @code{planner-sort-tasks-by-date}, and @code{planner-sort-tasks-by-link}. @end defopt @defopt planner-sort-undated-tasks-equivalent This option controls the behavior of task sorting on plan pages. By default, the value @samp{9999.99.99} causes dated tasks to be listed before undated tasks. To sort undated tasks before dated tasks, set this to a blank string. @end defopt @defopt planner-sort-tasks-automatically Non-nil means sort tasks whenever a planner file is saved. On day pages, tasks are sorted by status. On plan pages, they are sorted by status and date. Sorting can take a while. @end defopt @defopt planner-renumber-tasks-automatically Non-nil means renumber tasks from 1 to N whenever a planner file is saved. This allows you to refer to tasks in previous day pages using anchors like @samp{2003.08.12#A1}. If you use this function, make sure @code{planner-use-task-numbers} is non-nil so that new tasks are created with task numbers. @end defopt @defopt planner-align-tasks-automatically Non-nil means align tasks whenever a planner file is saved. This causes the status to line up in a neat column if you have less than 100 tasks. @end defopt @defopt planner-renumber-notes-automatically Non-nil means renumber the notes. If most of your notes are only on one page, you might like seeing the notes renumbered if you delete a note in the middle. However, if you use a lot of cross-referencing, note renumbering will break those links. @end defopt @subheading Functions @defun planner-sort-tasks Sort tasks according to planner-sort-tasks-key-function. By default, sort tasks according to priority and position on day pages, and according to status, priority, date, and position on plan pages. @end defun @defun planner-renumber-tasks Update task numbering. @end defun @defun planner-align-tasks Align tasks neatly. You can add this to @code{write-file-functions} to have the tasks automatically lined up whenever you save. For best results, ensure @code{planner-align-tasks} is run after @code{planner-renumber-tasks}. @end defun @defun planner-fix-tasks Sort, renumber and align tasks. @end defun @node Annotations, Interactive Lisp, Making Files Pretty, More about Planner @comment node-name, next, previous, up @section Annotations The context included when you create a task and the context included when you create a note are gained the same way. It sounds like black magic, but it turns out not to be. All that happens is, Planner has a list of functions, @code{planner-annotation-functions}. When you create a task from a buffer, or remember a note from a buffer, Planner goes through this list from top to bottom. The first one that returns true is the one it uses. For example, if you're in Wanderlust, and you hit the key you've bound to @code{planner-create-task-from-buffer}, it looks at this list and does something like this. Is it an ERC buffer? No. Is it a BBDB buffer? No. Are we in w3m? No. Are we in Wanderlust? Yes. So this function succeeds. It stops searching and runs the annotation function for Wanderlust, which in this case finds out who the message is from and what the message ID of the message is. It then takes those and constructs a link back to that message, with a link title something like @samp{Email from Joe Blogs}. So, you've read the email from Joe Blogs. He's asked you to do something and you've hit your key to add that task to your list of things to do. So what you end up with is a description of the task, and a link back to what made you create the task in the first place. The same happens with remembering notes, except that it ends up in the @samp{* Notes} section of your page instead. @subheading Options To change the behavior of annotations, customize the following options: @defopt planner-annotation-functions A list of functions tried in order by @command{planner-create-task-from-buffer} and other functions that pick up context. The first non-nil value returned is used as the annotation. To cause an item to @strong{not} be annotated, return the empty string @samp{""}. @end defopt @defopt planner-annotation-strip-directory File links are usually generated with the full path to the file so that you can easily tell apart files with the same base name. If @code{planner-annotation-strip-directory} is non-nil, though, only the base name of the file will be displayed. For example, a link to @samp{/foo/bar/baz} will be displayed as @samp{baz} and hyperlinked to the file. @end defopt @defopt planner-annotation-use-relative-file If t, always use relative filenames. @code{planner-annotation-use-relative-file} can also be a function that takes the filename and returns non-nil if the link should be relative. Filenames are resolved relative to the first directory of your Planner project in @code{muse-project-alist}. That is, the created link will be of the form @samp{../../somefile} instead of @samp{/absolute/path/to/file}. This can be helpful if you publish your planner files to the Net and your directory structure ensures that relative links resolve the same from your Plan pages and their respective publishing directory. @end defopt @node Interactive Lisp, Publishing, Annotations, More about Planner @comment node-name, next, previous, up @section Interactive Lisp with planner-lisp.el @cindex Lisp functions, using with Planner @cindex interactive Lisp fuctions, using with Planner @cindex @file{planner-lisp.el}, using You can include interactive Lisp functions in your planner pages. First, you need @file{planner-lisp.el}. Put this in your @file{.emacs} (or @file{_emacs}): @example (require 'planner-lisp) @end example Then, add a link to the Lisp function to your page, like: @example [[lisp:/plan][Plan]] @end example This will be rendered as @samp{Plan}. Selecting the link will run the @code{plan} function interactively. You can also execute other Lisp expressions. For example: @example [[lisp:/(planner-goto (planner-expand-name "+7"))][Next week]] @end example @file{planner-lisp.el} does not provide any interactive functions or keybindings. @node Publishing, Experimental Functions, Interactive Lisp, More about Planner @section Publishing @cindex publishing You can publish your planner files to a variety of different formats. For example, you can publish your planner in HTML and put it on a normal web server. No special server support is required. This gives you an easy way to keep other people up to date on your tasks, keep a web log, or simply organize information. Published files are stored in the path specified by @code{muse-project-alist} for your Planner project. Just copy the contents of this directory to your web server, and you're all set! Of course, publishing is completely optional. Here are some more features related to publishing: @menu * Publishing Planner pages:: planner-publish.el * Publishing Calendars:: planner-calendar.el * Authz Access Restriction:: planner-authz.el * RSS Publication:: Sharing notes with planner-rss.el * iCal Task Publication:: Sharing tasks with planner-ical.el * RDF Publication:: planner-rdf.el @end menu @node Publishing Planner pages, Publishing Calendars, Publishing, Publishing @comment node-name, next, previous, up @subsection Publishing Planner pages @cindex publishing @cindex @file{planner-publish.el}, using Publishing works by providing Muse with the settings and environment for Planner publishing. First, make sure that you have set up a proper @code{muse-project-alist} (@pxref{Creating Your Planner}). Second, add: @example (require 'planner-publish) @end example to your @file{.emacs} (or @file{_emacs}). To publish your entire Planner project, hit @kbd{C-c C-p} (@code{muse-project-publish}). To publish just the current buffer, hit @kbd{C-c C-t} (@code{muse-publish-this-file}). To automatically publish files when you save them, add the following code to your @file{~/.emacs} (or @file{_emacs}): @example (eval-after-load "muse-mode" '(add-hook 'after-save-hook #'(lambda () (when (planner-derived-mode-p 'muse-mode) (muse-project-publish nil))) nil t)) @end example @subheading Styles provided The following publishing styles are available. @table @code @cindex publishing styles, planner-html @item planner-html Publish Planner pages to HTML. @cindex publishing styles, planner-xhtml @item planner-xhtml Publish Planner pages to XHTML. @cindex publishing styles, planner-xml @item planner-xml Publish Planner pages to XML. @end table @subheading Options provided The following options may be customized to enhance your publishing experience. @table @code @item planner-publish-markup-regexps List of markup rules for publishing Planner pages. @item planner-publish-markup-functions Specify which function to use for publishing different kinds of markup. @item planner-publish-markup-tags A list of custom HTML-like tags to recognize when publishing. @item planner-xml-markup-strings Strings that are inserted to publish XML markup. @item planner-xml-header Header used when publishing Planner XML files. This may be text or a filename. @item planner-xml-footer Footer used when publishing Planner XML files. This may be text or a filename. @item planner-html-markup-strings Strings that are inserted to publish HTML markup. @item planner-html-style-sheet CSS stylesheet elements used in Planner HTML and XHTML files. This can also be one or more @samp{} tags. @item planner-html-header Header used when publishing Planner HTML files. This may be text or a filename. @item planner-html-footer Footer used when publishing Planner HTML files. This may be text or a filename. @item planner-xhtml-header Header used when publishing Planner XHTML files. This may be text or a filename. @item planner-xhtml-footer Footer used when publishing Planner XHTML files. This may be text or a filename. @item planner-html-inner-header Extra header section that can be embedded within @code{planner-html-header} and @code{planner-xhtml-header}. @item planner-html-inner-footer Extra header section that can be embedded within @code{planner-html-footer} and @code{planner-xhtml-footer}. @item planner-publish-prepare-regexps List of markup rules to apply before publishing a page with Planner. @item planner-publish-finalize-regexps List of markup rules to apply after publishing a page with Planner. @end table @node Publishing Calendars, Authz Access Restriction, Publishing Planner pages, Publishing @comment node-name, next, previous, up @subsection Publishing Calendars @cindex calendar, publishing @cindex @file{planner-calendar.el}, using To publish calendars in your day pages, it is necessary to do two steps. @itemize @item Add @code{(require 'planner-calendar)} to your configuration. @item Add a @samp{} tag to either your header, footer, or @var{planner-day-page-template}, depending on where you want it to appear. @end itemize To display a calendar based on a different day (given here as DAYPAGE), use @code{}. To get arrows to previous and next months to show up, use @code{}. The text in @var{planner-calendar-prev-month-button} and @var{planner-calendar-next-month-button} will be used for the arrows to the previous and next months, respectively. By default, Muse will not display the arrows properly, due to limitations in the special-escaping algorithm. To work around this, remove the @samp{&} rule from @var{muse-xml-markup-specials}, or from @var{muse-html-markup-specials} if you are using the 3.02.6 version of Muse. It is also possible to create a symlink from the current day page to the page name specified by @var{planner-calendar-today-page-name}. To accomplish this, add the following to your configuration. @example (eval-after-load "muse-publish" '(add-hook 'muse-after-publish-hook 'planner-calendar-create-today-link)) @end example @subheading Options @defopt planner-calendar-prev-month-button HTML text used for previous month buttons. @end defopt @defopt planner-calendar-next-month-button HTML text used for next month buttons. @end defopt @defopt planner-calendar-day-header-chars Number of characters to use for day column header names. @end defopt @defopt planner-calendar-today-page-name Default name for published today page link. @end defopt @subheading Functions @defun planner-calendar-create-today-link Add this function to @code{muse-after-publish-hook} to create a ``today'' soft-link to the newest published planner day page, on operating systems that support POSIX @command{ln}. @end defun @node Authz Access Restriction, RSS Publication, Publishing Calendars, Publishing @comment node-name, next, previous, up @subsection Authz Access Restriction @cindex @file{planner-authz.el}, using @cindex Mason, restricting portions with @cindex access, restricting @file{planner-authz.el} was written by Andrew J. Korty in order to allow the easy restriction of portions of published pages. It uses the HTML::Mason module available on CPAN (@url{http://www.cpan.org}). Setting up HTML::Mason is outside the scope of this document. Make sure that it works before trying out @file{planner-authz.el}. @file{planner-authz.el} modifies the behavior of @command{muse-project-publish} so that published pages follow access modifiers. This library lets you publish your planner pages while controlling access to certain portions of them to users you specify. When you load this library, you gain access to two additional markup directives to use in your planner pages. The @samp{} tag lets you restrict access to arbitrary content as follows: @example Here is a sentence everyone should see. This sentence also contains no sensitive data whatsoever. This sentence, however, talks about my predilection for that French vanilla instant coffee that comes in the little tin, and I'm embarrassed for anyone else to know about that. And here's some more perfectly innocuous content. @end example You can use @samp{} tags to mark up entire paragraphs, tasks, notes, and anything else. The tags are replaced with Mason code in the published pages. The @samp{#authz} directive restricts access to an entire page. A Mason call is added to this page to generate a 403 error when someone not listed tries to access it. Any notes or tasks on a @samp{#authz}-protected page are also wrapped in Mason code on linked pages. To add a @samp{#authz} directive to a Muse page, place @samp{#authz} followed by a space-delimited list of users on one line. For example: @example #authz ajk sacha @end example @subheading Getting started Add the following to your .emacs file to cause @kbd{M-x muse-project-publish} to automatically use planner-authz features. @example (require 'planner-authz) @end example @subheading Diary markup If your pages have a section with diary entries maintained by planner-appt.el (or by any other means), you can control access to these entries. First, customize @code{planner-section-tagnames} to map your diary section ("* Schedule", in this example) to a tag called "diary-section". An example follows. @example (add-to-list 'planner-section-tagnames '("Schedule" . "diary-section")) @end example If the name of your diary section is "* Diary", you will not need to customize @code{planner-section-tagnames} by default. Then make sure the diary entries you want restricted contain a corresponding plan page name in parentheses, as in the following example. @example 10:00 10:30 Meeting with boss (WorkStuff) @end example @subheading Options @defopt planner-authz-project-default Default access list for project pages (not day pages). If a given project page doesn't contain a @samp{#authz} tag, it will receive the access list defined here. If this variable is nil, all users will be allowed to view the page. No corresponding variable is provided for day pages because it doesn't seem like you'd ever want to control access based on what day it was. (But I will accept patches. :) Notes and tasks referencing pages without @samp{#authz} tags will also be restricted to the users listed here. @end defopt @defopt planner-authz-day-note-default Default access list for notes on day pages not associated with any project. There is way to set a default for notes on project pages for the reason above; they would only be associated with date pages anyway. @end defopt @defopt planner-authz-day-task-default Same as @kbd{planner-authz-day-note-default}, but for tasks. @end defopt @subheading Functions @defun planner-authz-publish-index Publish an index for the planner marked up with Mason code. Only those links to pages which the remote user is authorized to access will be shown. @end defun @node RSS Publication, iCal Task Publication, Authz Access Restriction, Publishing @comment node-name, next, previous, up @subsection RSS Publication @cindex @file{planner-rss.el}, using @cindex notes, RSS @cindex RSS @file{planner-rss.el} allows you to publish your notes in the RSS 2.0 XML format for blog syndication. You will also want to customize the following variables: To manually add the current note to all the matching RSS feeds, invoke @command{planner-rss-add-note}. You can specify a filename with the universal prefix, like this: @kbd{C-u M-x planner-rss-add-note}. If you use the @file{remember-planner.el} module to create notes, you can automatically publish new notes to RSS feeds by adding the following code to your @file{.emacs} (or @file{_emacs}). @example (add-to-list 'remember-planner-append-hook 'planner-rss-add-note t) @end example @subheading Options @defopt planner-rss-base-url Base absolute URL for published blog entries. Should include trailing @samp{/}. @end defopt @defopt planner-rss-category-feeds Rules for automatic categorization of posts and publishing to RSS files. A blog entry is matched against each condition. If it matches the regular expression or the function returns a non-nil value, the blog entry is copied into the specified file. @end defopt @defopt planner-rss-feed-limits A list of regular expressions that match feed filenames and the size and item limits for feeds that match. For example, you can use @samp{(("." nil 10))} to ensure that all feeds are limited to the 10 most recent items. @end defopt @subheading Functions @file{planner-rss.el} defines the following interactive functions: @defun planner-rss-add-note @var{feed} Export the current note using @code{planner-add-item}. If @var{feed} is specified, add the entry to the specified file. Else, add the entry to all matching RSS feeds specified by @code{planner-rss-category-feeds}. @end defun @node iCal Task Publication, RDF Publication, RSS Publication, Publishing @comment node-name, next, previous, up @cindex @file{planner-ical.el}, using @subsection iCal Publication iCal is an Internet Engineering Task Force (IETF) standard for calendaring and scheduling. @uref{http://www.ietf.org/rfc/rfc2445.txt} You can export your tasks to the iCal format using @file{planner-ical}. Add @code{(require 'planner-ical)} to your @file{~/.emacs}. Then you can use @kbd{M-x planner-ical-export-page} to display the iCal equivalent of tasks on a page, which you can then save to a file. To export today's tasks to a file in your publishing directory, add the following to your @file{~/.emacs}. @example (planner-ical-export-file (planner-today) (expand-file-name "tasks.ics" (muse-style-element :path (car (cddr (muse-project planner-project)))))) @end example @subheading Functions @defun planner-ical-export-page page &optional file Export PAGE's tasks in the iCal format. If FILE is non-nil, results are saved to that file. If FILE is nil, results are displayed in a `planner-ical-export-buffer'. @end defun @defun planner-ical-export-this-page Display the tasks on the current page in iCal format. @end defun @node RDF Publication, , iCal Task Publication, Publishing @comment node-name, next, previous, up @subsection RDF Publication @cindex @file{planner-rdf.el}, using @cindex RDF, publishing to Put planner-rdf.el in a directory that is in your Emacs load-path and the following into your ~/.emacs file: @example (require 'planner-rdf) (eval-after-load "muse-publish" '(progn (add-hook 'muse-after-publish-hook 'planner-rdf-publish-file) (add-hook 'muse-after-publish-hook 'planner-rdf-publish-index))) @end example @menu * Publishing with planner-rdf:: * planner-rdf Tags:: * planner-rdf Usage Examples:: @end menu @node Publishing with planner-rdf, planner-rdf Tags, RDF Publication, RDF Publication @subsubsection Publishing with planner-rdf Planner-rdf is now included in the normal Planner publishing process. Pressing @key{C-p} will create a .owl and a .rdf file for every planner file. Additionally it creates an index, @file{index.rdf}. By default all generated files will be stored in the normal Planner publishing directory, where the HTML files end up. If you would ike to change that, set the variable @code{planner-rdf-directory} to the desired location. The generated files: @itemize @item @file{index.rdf} - a collection with pointers to the @file{.rdf} files. @item @file{.rdf} - contains Dublin Core metadata about the files related to the current Planner page. Currently it contains metadata about the source file, the Emacs plan page, the generated HTML page, and the generated OWL file. @item @file{.owl} - contains task and note data from the Planner file. Task information is stored completely. For notes, the note headline is stored. @end itemize @node planner-rdf Tags, planner-rdf Usage Examples, Publishing with planner-rdf, RDF Publication @subsubsection planner-rdf Tags Besides the factual information, e.g. the task status or description, planner-rdf extracts links (in the format @samp{[[...][...]]} or @samp{[[...]]}) and tags (@samp{@{@{...:...}@}@}) from tasks and notes (including the notes text). Links and tags provide context for the plan elements and so are stored and linked with the containing elements. Links point to locations that can be used to enrich the information in the Planner pages (e.g, by retrieving data from them and adding it), tags -- like the one for the task ids @samp{@{@{Tasks:198@}@}} -- can be used to express abstract qualities. Some examples: @itemize @item an @samp{@{@{audience:myteam@}@}} tag, can be used to restrict publishing of items to a certain user group; @item a @samp{@{@{lang:de@}@}} tag, signifying the language of the text; @item a @samp{@{@{location:Hamburg@}@}} tag, can be used to make geographic reference to an entity that is not stored in your address book, bbdb. @end itemize What tags to use is up to the user. Planner-rdf makes no assumptions about them, it just extracts and stores them. Only the applications using the data know what to do with them. @node planner-rdf Usage Examples, , planner-rdf Tags, RDF Publication @subsubsection Usage Examples Report generation with OpenOffice The Perl file @file{this-week.pl} (@url{http://www.rainervolz.de/planner-rdf/this-week.pl}) creates a simple report for the current week. The script extracts task and note information from the generated OWL files and inserts it into a simple OpenOffice Writer document. Nothing fancy, just a proof of concept, to show how planner-rdf can be used to integrate Planner Mode with other applications. Besides Perl and OpenOffice you'll need the Redland RDF Application Framework (@url{http://www.redland.opensource.ac.uk/}). It is used to process the RDF data. Redland is small, but powerful, and available for many platforms and languages. As an example the application loads the RDF data each time it is run. In the real world you probably would use Redland to store the Planner data in a database, to save the loading step each time you access the data. Importing Planner data into Protege Protege is a popular ontology editor and knowledge management application. A simple way to import data into it, is to provide a OWL file that contains the data as well as the schema. To do this: @itemize @item Use @file{planner2protege.pl} (@url{http://www.rainervolz.de/planner-rdf/planner2protege.pl}) to combine all OWL files into a single one. @item Use CWM (@url{http://www.w3.org/2000/10/swap/doc/cwm.html}) to combine schema and data, with @code{python cmw --rdf planner-rdf.owl planner-data.owl --think --rdf >planner2.owl} @end itemize Not the most straightforward process, but it works. The resulting file, here planner2.owl, can then be loaded into Protege. @node Experimental Functions, , Publishing, More about Planner @comment node-name, next, previous, up @section Experimental Functions @cindex @file{planner-experimental.el}, using @cindex experimental functions, Planner These functions are experimental. This means that they may not do exactly what you expect them to do, so keep backups, be careful, and don't blame us. To use these functions, make sure that @file{planner-experimental.el} is in your load path, and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-experimental) @end example @subheading Functions @file{planner-experimental.el} defines the following interactive functions: @defun planner-search-notes-next-match Jump to the next matching entry. Call after @code{planner-search-notes}. @end defun @defun planner-search-notes-previous-match Jump to the previous matching entry. Call after @code{planner-search-notes}. @end defun @defun planner-remove-duplicates Remove duplicate tasks. @end defun @file{planner-experimental.el} does not define any keybindings. @node Managing Your Information, Advanced Configuration, More about Planner, Top @comment node-name, next, previous, up @chapter Managing Your Information Planner can be integrated with other Emacs and even some non-Emacs programs by loading additional modules. You can pick and choose from these modules, choosing those that work with programs you use and that produce information you want to have included in your Planner pages. @menu * E-mail:: Linking notes and tasks to messages * Scheduling and Time:: Tracking appointments and where your time goes * Finances:: Display your account balances and more * Contacts and Conversations:: BBDB and ERC * Tracking Research and Resources:: The Web, bibliographies, and bookmarks * Tracking Development:: @end menu @node E-mail, Scheduling and Time, Managing Your Information, Managing Your Information @comment node-name, next, previous, up @section E-mail Planner can work together with several different Emacs e-mail clients. If you load the appropriate module for the e-mail client you use, then your notes and tasks can be annotated with information pointing to the specific e-mail message you were reading when you created that note or task. When you are looking at the note or task, you will be able to jump straight to that message. @menu * Unix mail:: Unix mailboxes: planner-unix-mail.el * Gnus:: Gnus mail and news reader: planner-gnus.el * VM:: VM mail reader: planner-vm.el * Wanderlust:: Wanderlust mail reader: planner-wl.el * MH-E:: MH-E mail reader: planner-mhe.el * Rmail:: Rmail: planner-rmail.el @end menu @node Unix mail, Gnus, E-mail, E-mail @comment node-name, next, previous, up @subsection Unix mail @cindex @file{planner-unix-mail.el}, using @cindex mbox, using Planner with @cindex Unix mail, using Planner with @cindex mail client, using Planner with This module supports links from any kind of Unix mailbox (mbox). To use this module, make sure that @file{planner-unix-mail.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-unix-mail) @end example Unix mail URLs are of the form: @example ;; mail://PATH/TO/INBOX/message-id @end example Annotations will be of the form: @smallexample [[mail://PATH/TO/INBOX/E1AyTpt-0000JR-LU%40sacha.ateneo.edu][E-mail from Sacha Chua]] @end smallexample @file{planner-unix-mail.el} does not define any interactive functions or create any new keybindings. @node Gnus, VM, Unix mail, E-mail @comment node-name, next, previous, up @subsection Gnus @cindex Gnus, using Planner with @cindex mail client, using Planner with, Gnus @cindex @file{planner-gnus.el}, using To use this module, make sure that it is in your load path and put this in your @file{.emacs} (or @file{_emacs}): @example (require 'planner-gnus) (planner-gnus-insinuate) @end example With this module loaded, when you create tasks from Gnus summary or message buffers, the tasks will be annotated with information from the message you were looking at when you created each task. A link will also be created on your planner page that you can select in order to return to the message. So, the created task will look something like this: @smallexample #A34 _ Send writing to publishme.com from [[gnus://alt.books.beatgeneration/][E-Mail from editor@@verizon.net]] @{@{Tasks:71@}@} ([[Writing]]) @end smallexample This module also binds @kbd{C-c C-t} in the Gnus summary and article views to the command to create a new task. @file{planner-gnus.el} does not define any interactive functions. For more information about Gnus, see @inforef{Top, The Gnus Newsreader, gnus}. @node VM, Wanderlust, Gnus, E-mail @comment node-name, next, previous, up @subsection VM @cindex VM, using Planner with @cindex mail client, using Planner with, VM @cindex @file{planner-vm.el}, using To use this module, make sure that @file{planner-vm.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-vm) @end example VM URLs are of the form: @example vm://path/to/inbox/message-id @end example Annotations will be of the form: @smallexample [[vm://home/test/INBOX/][E-mail from Sacha Chua]] @end smallexample @file{planner-vm.el} does not define any interactive functions or keybindings. @node Wanderlust, MH-E, VM, E-mail @comment node-name, next, previous, up @subsection Wanderlust @cindex Wanderlust, using Planner with @cindex mail client, using Planner with, Wanderlust @cindex @file{planner-wl.el}, using To use this module, make sure that @file{planner-wl.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-wl) @end example Then, when you call @kbd{M-x planner-create-task-from-buffer} from Wanderlust summary or message buffers, the task will be created with the correct annotation. @subheading Keys To add keybindings to Wanderlust, call: @example (planner-wl-insinuate) @end example This binds @kbd{C-c C-t} to @command{planner-create-task-from-buffer}. @node MH-E, Rmail, Wanderlust, E-mail @comment node-name, next, previous, up @subsection MH-E @cindex MH-E, using Planner with @cindex mail client, using Planner with, MH-E @cindex @file{planner-mhe.el}, using To use this module, make sure that @file{planner-mhe.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-mhe) @end example Then, when you call @kbd{M-x planner-create-task-from-buffer} from MH-E summary or message buffers, the task will be created with the correct annotation. @file{planner-mhe} does not define any interactive functions. @node Rmail, , MH-E, E-mail @comment node-name, next, previous, up @subsection Rmail @cindex Rmail, using Planner with @cindex mail client, using Planner with, Rmail @cindex @file{planner-rmail.el}, using To use this module, make sure that @file{planner-rmail.el} is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-rmail) @end example Rmail URLs are of the form: @example rmail://message-id @end example Annotations will be of the form: @smallexample [[rmail://][E-mail from Sacha Chua]] @end smallexample @file{planner-rmail.el} does not define any interactive functions or create any new keybindings. For more information about Rmail, see @inforef{Rmail, Reading Mail With Rmail, Emacs}. @node Scheduling and Time, Finances, E-mail, Managing Your Information @comment node-name, next, previous, up @section Scheduling and Time @menu * Diary:: Using the Emacs diary: planner-diary.el * Appointments:: Appointments in plan pages: planner-appt.el * Timeclock:: Time tracking: planner-timeclock.el * schedule.el:: Project completion: planner-schedule.el @end menu @node Diary, Appointments, Scheduling and Time, Scheduling and Time @comment node-name, next, previous, up @subsection Diary @cindex diary, using Planner with @cindex @file{planner-diary.el}, using If you use Emacs's diary feature, Planner-Diary could be helpful for you. It puts all diary entries for the current day in the @samp{* Diary} section of your day plan page. This section is updated every time you display the file in Emacs. By default the diary section of past pages is not updated; it's pretty unlikely that you want to add new diary entries for the past. (@pxref{Diary, , , Emacs, GNU Emacs Manual}) If you want to use @file{planner-diary.el}, make sure the file is in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-diary) @end example @file{planner-diary.el} needs @command{fancy-diary-display}. To use @command{fancy-diary-display}, add this to your @file{.emacs} (or @file{_emacs}): @example (add-hook 'diary-display-hook 'fancy-diary-display) @end example You can use Planner-Diary in two different ways: @enumerate @item If you want the saved files to contain your entries and not just a line of Lisp, add the following lines to your @file{.emacs} (or @file{_emacs}): @example (setq planner-diary-use-diary t) (planner-diary-insinuate) @end example You should also customize or set @code{planner-day-page-template} to include a @samp{* Diary}: @example (setq planner-day-page-template "* Tasks\n\n\n* Schedule\n\n\n* Diary\n\n\n* Notes") @end example @kbd{C-c C-e} updates the diary sections. @kbd{C-u C-c C-e} forces an update---it inserts the diary section for the day, even if the day is in the past or if there is no @samp{Diary} section in the buffer. @item (GNU EMACS ONLY) You can put the following line of Lisp code in your day plan pages to display your diary entries: @example (planner-diary-entries-here) @end example You can do this automatically for all day plan pages: @smallexample (setq planner-day-page-template "* Tasks\n\n\n* Diary\n\n(planner-diary-entries-here) \n* Notes") @end smallexample When you open a day plan page outside Emacs, you will see the line of Lisp code and not your diary entries. @end enumerate If you want to see your diary entries for more than just one day, set @code{planner-diary-number-of-days} accordingly. This works for either of the two approaches. These diary sections are only intended for display. Editing them will not affect your diary file. If you want to add entries to your diary, you should use the usual Emacs diary and calendar methods for doing that, or call @code{planner-diary-add-entry}. If you want to use the Cal-Desk package, simply follow the instructions in @file{cal-desk.el}. If you get the Cal-Desk layout from the Calendar buffer, you get it in the day plan buffer, too. If you use Planner-Diary, you might consider using the Calendar support of Planner. (@pxref{Calendar/Diary, , , Emacs, GNU Emacs Manual}) To get Calendar integration, add this to your @file{.emacs} (or @file{_emacs}): @example (planner-insinuate-calendar) @end example If @code{planner-diary-create-section-flag} is non-nil, sections are always inserted if necessary. @cindex planner2diary.py, using If you want to import Planner entries into your Diary file, the @file{planner2diary.py} script will accomplish this for you. To use it, execute @code{planner2diary.py} on the command line, specifying your planner directory as the first and only argument. @subheading Options @defopt planner-diary-create-section-flag Non-nil means create the requested diary sections if they do not exist. By default, planner-diary tries to create the section. If you want more control over your pages, you can set this to nil. Trying to write a diary section to a page that does not have it yet will then result in an error. @end defopt By default, planner-diary lists only the appointments you have on that day. If you want the date headers included even when showing the diary entries for a single day, set planner-diary-include-all-output to non-nil. @defopt planner-diary-include-all-output-flag Non-nil means don't omit any data when copying diary entries into day pages. @end defopt @subheading Functions @file{planner-diary.el} defines the following interactive functions: @defun planner-diary-add-entry date time text Prompt for a diary entry to add to @code{diary-file} on @var{date}. Uses @code{planner-annotation-functions} to make hyperlinks. @var{time} and @var{text} are used in the description." @end defun @defun planner-diary-insert-diary force Insert the fancy diary for the day into the day plan file. If @var{force} is non-nil, insert a diary section even if there is no @var{planner-diary-string} in the buffer. @end defun @defun planner-diary-insert-diary-maybe force Maybe insert the fancy diary for the day into the day plan file. If the current day is in the past and @var{force} is nil, don't do anything. If @var{force} is non-nil, insert a diary section even if there is no @code{planner-diary-string} in the buffer. @end defun @defun planner-diary-insert-appts force Insert the diary appointments for the day into the day plan file. If @var{force} is non-nil, insert a diary appointments section even if there is no @code{planner-diary-appts-string} in the buffer. @end defun @defun planner-diary-insert-appts-maybe force Maybe insert the diary appointments for the day into the day plan file. If the current day is in the past and @var{force} is nil, don't do anything. If @var{force} is non-nil, insert a diary appointments section even if there is no @code{planner-diary-appts-string} in the buffer. @end defun @defun planner-diary-insert-cal-desk force Insert the cal-desk diary for the day into the day plan file. If @var{force} is non-nil, insert a cal-desk diary section even if there is no @code{planner-diary-cal-desk-string} in the buffer. @end defun @defun planner-diary-insert-cal-desk-maybe force Maybe insert the cal-desk diary for the day into the day plan file. If the current day is in the past and @var{force} is nil, don't do anything. If @var{force} is non-nil, insert a cal-desk appointments section even if there is no @code{planner-diary-cal-desk-string} in the buffer. @end defun @defun planner-diary-insert-public force Insert the public diary for the day into the day plan file. If @var{force} is non-nil, insert a public diary section even if there is no @code{planner-diary-public-string} in the buffer. @end defun @defun planner-diary-insert-public-maybe force Maybe insert the public diary for the day into the day plan file. If the current day is in the past and @var{force} is nil, don't do anything. If @var{force} is non-nil, insert a public appointments section even if there is no @code{planner-diary-public-string} in the buffer. @end defun @defun planner-diary-insert-private force Insert the private diary for the day into the day plan file. If @var{force} is non-nil, insert a private diary section even if there is no @code{planner-diary-private-string} in the buffer. @end defun @defun planner-diary-insert-private-maybe force Maybe insert the private diary for the day into the day plan file. If the current day is in the past and @var{force} is nil, don't do anything. If @var{force} is non-nil, insert a private appointments section even if there is no @code{planner-diary-private-string} in the buffer. @end defun @defun planner-diary-insert-all-diaries force Update all diary sections in a day plan file. If @var{force} is non-nil, insert a diary section even if there is no section header. It only inserts diaries if the corresponding @code{planner-diary-use-}* variable is @samp{t}. @end defun @defun planner-diary-insert-all-diaries-maybe force Update all diary sections in a day plan file. If the current day is in the past and @var{force} is nil, don't do anything. If @var{force} is non-nil, insert a diary section even if there is no section header. It only inserts diaries if the corresponding @code{planner-diary-use-}* variable is @samp{t}. @end defun @defun planner-diary-show-day-plan-or-diary Show the day plan or diary entries for the date under point in calendar. Add this to @code{calendar-move-hook} if you want to use it. In that case, you should also @command{remove-hook} @samp{planner-calendar-show} from @code{calendar-move-hook}. @end defun @subheading Keys @file{planner-diary.el} adds the following keybinding to Planner, if @command{planner-diary-insinuate} is in your @file{.emacs} (or @file{_emacs}): @itemize @item @kbd{C-c C-e} updates the diary sections by calling @code{planner-diary-insert-all-diaries-maybe}. @end itemize @menu * Planner-Diary Advanced Features:: @end menu @node Planner-Diary Advanced Features, , Diary, Diary @comment node-name, next, previous, up @subsubsection Planner-Diary Advanced Features @cindex diary, using Planner with @cindex @file{planner-diary.el}, advanced features The features described here are part of the development version. They are subject to change without notice. They may be buggy. The documentation may be inaccurate. Use at your own risk. There is a lot of code redundancy in the development version. This is intentional and makes it easier to change the code for one type of diary section without breaking others. @subheading Diary views @cindex @file{planner-diary.el}, views Currently Planner-Diary supports six different views of your diary entries: @enumerate @item Ordinary fancy diary display (what you get by pressing @kbd{d} in the calendar buffer with @code{fancy-diary-display} switched on) @item Schedule/Appointments (all entries from 1 that have a time assigned to them @item Diary without appts (1 without 2) @item cal-desk display (appts on top, non appts entries at bottom) @item A private diary (same as 1, but uses a different diary-file) @item A public diary (same as 1, but uses a different diary-file) @end enumerate Put the following line of Lisp code in your day plan pages to display your diary entries: @example (planner-diary-entries-here) @end example The function @code{planner-diary-entries-here} takes two optional arguments---the diary file you want to use and the number of days you want to display. @subheading Exporting Planner-specific Diary files @cindex @file{planner-diary.el}, exporting entries If you would like to export diary entries from your Planner pages to separate Diary files, add @code{(require 'planner-export-diary)} to your config. The following steps describe the usage of the functions and options contained in this file. @enumerate @item Customize @code{planner-export-diary-file}. The default value is ``~/diary.planner''. @item Add the following line to your main Diary file (default: ``~/diary''). @example #include ~/diary.planner @end example @item Then, call @command{M-x planner-export-diary-future} whenever you want future diary entries published. You can automatically publish entries by adding either of the following to your .emacs. @itemize @item (planner-export-diary-future) Publish future entries on startup. @item (add-hook 'planner-mode-hook 'planner-export-diary-setup) Publish future entries whenever you save a Planner file. @end itemize @end enumerate @node Appointments, Timeclock, Diary, Scheduling and Time @comment node-name, next, previous, up @subsection Appointments @cindex appointments @cindex @file{planner-appt.el}, using If you would like to use planner for your appointment alerts instead of using the diary system, you might like to try @file{planner-appt}. According to your preferences, you may choose from two different approaches. Appointments in task descriptions on today's plan page are like this: @example #A _ @@12:45 Do something (TaskPool) @end example @noindent and appointments in today's schedule section are like this: @example * Schedule 9:00 | 12:00 | Read Simmel's Philosophy of Money @@12:45 | | Do Something Else @@13:00 | 14:00 | lunch @end example @noindent You can even use both at the same time if you like. @c Jim Ottaway : Changed these kinds of heading @c back to @unnumberedsec, but left the originals commented out in @c case there was a good reason for the @strong formatting. @c @noindent @c @strong{Usage} @unnumberedsubsubsec Usage In the file where you configure Planner, add one of the following. @itemize @item For task-based appointments: @code{(planner-appt-use-tasks)} @item For schedule-based appointments: @code{(planner-appt-use-schedule)} @item For both task- and schedule-based appointments: @code{(planner-appt-use-tasks-and-schedule)} @end itemize @noindent And finally if you want everything to be updated automatically add: @example (planner-appt-insinuate) @end example If you don't want to do the insinuation then you can call: @example M-x planner-appt-update @end example @noindent after editing appointments on the page (note that this is not necessary if you use tasks for the appointments and you don't edit the task descriptions outside of @code{planner-edit-task-description}). Try both methods; if you find that you prefer one over the other, use one of the specific @code{planner-appt-use-} functions, as there are some performance gains when using one method exclusively. @menu * Task-based Appointments:: * Schedule-based Appointments:: * Viewing Appointments:: * Appointment Updating on Save:: * Appointment and Calendar Integration:: * Appointment Hooks:: @end menu @node Task-based Appointments, Schedule-based Appointments, Appointments, Appointments @comment node-name, next, previous, up @subsubsection Task-based Appointments @cindex appointments, task-based @cindex task-based appointments A task has an appointment if it looks like this: @example #A _ @@12:45 Do something (TaskPool) @end example @noindent i.e., if it has @@ followed by a time at the beginning. This means the task is a regular appointment, and will not be carried forward at the start of a new day. Alternatively, it may have a !, like this: @example #A _ !12:45 Do something else (TaskPool) @end example @noindent This makes it a "nagging" appointment, which @emph{will} be carried forward. It will, however, lose the appointment time in the process. This may seem like a strange feature, but here is Henrik's reasoning: @quotation Sometimes I have a task that I want to do at a certain time, so I make it an appointment. If I don't get around to doing it anyway, I want it to be carried forward. Basically, I sometimes use appointments on tasks to annoy me until I get them done. :) @end quotation You can edit, move and delete tasks with the usual functions, and appointments will be updated automatically. You can update all task appointments on your page with @example M-x planner-appt-update @end example @c @noindent @c @strong{Cyclic Entries} @unnumberedsubsubsec Cyclic Entries @cindex appointments, cyclic task entries If you have @file{planner-cyclic} (@pxref{Cyclic Tasks}) loaded, entries in your cyclical tasks file such as @example Friday #A _ @@12:45 staff meeting @end example @noindent will appear every Friday and there will be an appointment alert set up. @c @noindent @c @strong{Appointments Section} @unnumberedsubsubsec Appointments Section @cindex appointments, appointments section You can have all task-based appointments copied to a separate section, providing an overview of your appointments. To do this, add @example (setq planner-appt-task-use-appointments-section-flag t) @end example @noindent to your configuration, or use @kbd{M-x customize-variable}. The variable @code{planner-appt-task-appointments-section} is the name of the section where the appointments will be copied. By default, it is set to @code{"Schedule"}, which means that task appointments will be intermingled with schedule entries. It is also a good idea to add the section you wish to use to @code{planner-day-page-template} in order to control where that section will appear on the page (otherwise it will appear at the top). The format of the appointments follows that of a schedule; if you don't like the way it looks, you can write something different and set @code{planner-appt-format-appt-section-line-function} appropriately. See the documentation for @code{planner-appt-format-appt-section-line-function} for details. It should be fairly easy to see what needs to be done if you look at the source for the default function (which is @code{planner-appt-format-appt-section-line}). If the section specified in @code{planner-appt-task-appointments-section} is the same as the schedule section specified in @code{planner-appt-schedule-section} (by default @code{"Schedule"}), the default formatting function adds a @samp{#} to the description so that one can visually distinguish appointments from the task list from those that have been added to the schedule. @node Schedule-based Appointments, Viewing Appointments, Task-based Appointments, Appointments @comment node-name, next, previous, up @subsubsection Schedule-Based Appointments @cindex appointments, schedule-based @cindex schedule-based appointments Some scheduled tasks require reminders, others don't. In this schedule: @example * Schedule 9:00 | 12:00 | Read Simmel's Philosophy of Money @@12:45 Do Something Else @@13:00 | 14:00 | lunch @@14:30 | | Meet jrs to discuss his dissertation @@16:00 Test Society seminar 18:00 go home @end example @noindent those that have an @@ prefix will be added to the appointment reminder list; the others will not. The formats that are recognized are fairly flexible, as you can see from the example. If you change your schedule, you can update the appointment list with @example M-x planner-appt-update @end example @noindent You can also have the schedule sorted as part of the update, if you have this in your configuration: @example (setq planner-appt-sort-schedule-on-update-flag t) @end example @c @noindent @c @strong{Cyclical Entries} @unnumberedsubsubsec Cyclical Entries @cindex appointments, cyclic schedule entries You can also have cyclical schedule entries(@pxref{Cyclic Tasks}) if you add @example (planner-appt-schedule-cyclic-insinuate) @end example @noindent to your configuration. If you put an entry in your cyclical task file like this @example Friday @@12:45 | 13:45 | Staff Meeting @end example @noindent then it will appear in your schedule every Friday, and an appointment alert will be set up. @node Viewing Appointments, Appointment Updating on Save, Schedule-based Appointments, Appointments @comment node-name, next, previous, up @subsubsection Viewing Appointments @cindex appointments, viewing The command @command{planner-appt-show-alerts} will show all appointment alerts currently scheduled. @subheading Functions There are two commands that show appointments in the future; the one displays them in a pop-up buffer, the other puts the information into the current day page. @deffn {Command} planner-appt-forthcoming-display &optional days Display a buffer of appointments for today and the next @var{days}. Optional prefix argument @var{days} is the number of days ahead to look. Its default value is defined by @code{planner-appt-forthcoming-days}. @end deffn @deffn {Command} planner-appt-forthcoming-update-section &optional days In today's plan page, add or update a list of forthcoming appointments. Optional prefix argument @var{days} is the number of days ahead to look. Its default value is defined by @code{planner-appt-forthcoming-days}. The section heading to use is defined by @code{planner-appt-forthcoming-appt-section}. @end deffn @subheading Options @defopt planner-appt-forthcoming-days The number of days to look ahead for forthcoming appointments. The default value is seven days. @end defopt @defopt planner-appt-forthcoming-appt-section The name of the section to use for inserting a list of forthcoming appts. The default value is @code{"Forthcoming Appointments"}. @end defopt @defopt planner-appt-forthcoming-show-day-names-flag When non-nil (the default), day names will be shown in forthcoming appointments. @end defopt @defopt planner-appt-forthcoming-repeat-date-string String to insert for repeated dates. When there are multiple appointments for a date, the date is inserted in the first appointment and the others have this string in their date cell. If the string consists of anything other than whitespace, then a link to the day page for the appoinment is created. @end defopt @defopt planner-appt-forthcoming-look-at-cyclic-flag When non-nil, find forthcoming appointments in the cyclic diary file (@pxref{Cyclic Tasks}) as well as in plan pages. Default is @samp{t}. @end defopt @node Appointment Updating on Save, Appointment and Calendar Integration, Viewing Appointments, Appointments @comment node-name, next, previous, up @subsubsection Appointment Updating on Save @cindex appointments, updating on save @subheading Options @defopt planner-appt-update-appts-on-save-flag When non-nil, update appointment reminders whenever today's plan page is saved. Default value is @samp{nil}. @end defopt @node Appointment and Calendar Integration, Appointment Hooks, Appointment Updating on Save, Appointments @comment node-name, next, previous, up @subsubsection Appointment and Calendar Integration Not strictly part of appointment handling, but if one isn't using the diary, marking dates with plan pages seems to make sense. @subheading Functions @defun planner-appt-calendar-insinuate Add a hook to diary display so that dates in the calendar that have day pages are highlighted @end defun @node Appointment Hooks, , Appointment and Calendar Integration, Appointments @comment node-name, next, previous, up @subsubsection Appointment Hooks @subheading Options @defvr {Hook} planner-appt-update-hook Hook run after @code{planner-appt-update} has updated the appointment list. @end defvr @node Timeclock, schedule.el, Appointments, Scheduling and Time @comment node-name, next, previous, up @subsection Timeclock @cindex @file{planner-timeclock.el}, using @cindex @file{planner-timeclock-summary.el}, using @cindex @file{planner-timeclock-summary-proj.el}, using @cindex timeclock, using Planner with This module allows you to clock in and clock out of your projects (@pxref{Time Intervals, , , Emacs, GNU Emacs Manual}) You can also generate reports with the @code{} tag. You may want to read the ``Keeping Track of Time'' page to see how you can use planner-timeclock to produce detailed reports; @xref{Keeping Track of Time}. @file{timeclock.el} is part of GNU Emacs. If you are using XEmacs, please use the version of @file{timeclock.el} that comes with Planner in the @file{contrib} directory. With @file{planner-timeclock.el} loaded, @command{planner-task-in-progress} clocks in a task. To clock out, use @command{planner-task-done} or @command{timeclock-out}. @file{planner-timeclock.el} defines the following keybindings: @itemize @item @kbd{C-c C-i}: @code{planner-task-in-progress}. @item @kbd{C-c C-o}: @code{timeclock-out}. @item @kbd{C-c C-T C-i}: @code{planner-timeclock-in}. (XEmacs) @item @kbd{C-c C-T C-o}: @code{timeclock-out}. (XEmacs) @item @kbd{C-c C-S-t C-i}: @code{planner-timeclock-in}. (GNU Emacs) @item @kbd{C-c C-S-t C-o}: @code{timeclock-out}. (GNU Emacs) @end itemize If you use @code{timeclock} a lot, you may also be interested in Dryice Liu's @file{planner-timeclock-summary.el}, which produces timeclock reports for planner files. Here is a sample report: @example Project | Time| Ratio| Task PlannerMaintenance | 0:03:58| 1.1%| Merge doc patch | 0:17:09| 5.0%| Track down subdirectories | 0:18:11| 5.3%| Merge planner-timeclock-summary-proj.el Total: | 0:39:18| 11.4%| JapanCaseStudy | 2:37:56| 45.6%| Prototype search result page | 0:31:50| 9.2%| Update design documents Total: | 3:09:46| 54.8%| ChristmasLetter | 1:46:37| 30.8%| Write and send my Christmas letters Total: | 1:46:37| 30.8%| LinuxPeople | 0:10:29| 3.0%| Send questions for Linux in Education Total: | 0:10:29| 3.0%| @end example If you add @code{(require 'planner-timeclock-summary)} to your @file{~/.emacs}, you can then use it in two ways. @itemize @item Display a temporary buffer Call @code{planner-timeclock-summary-show} and Emacs will ask you which day's summary do you want. Choose the date as anywhere else of Emacs planner, and a tempory buffer will be displayed with the timeclock summary of that day. To review tasks over a date range, use @code{planner-timeclock-summary-show-range}. You can use a regexp or a function to filter tasks by calling @code{planner-timeclock-summary-show-range-filter}. @item Rewrite sections of your planner Choose this approach if you want timeclock summary to be in their own section and you would like them to be readable in your plain text files even outside Emacs. Caveat: The timeclock summary section should already exist in your template and will be rewritten when updated. Tip: Add @code{planner-timeclock-summary-section} (default: @samp{"Timeclock"}) to your @code{planner-day-page-template}. To use, call @code{planner-timeclock-summary-update} in the planner day page to update the section. If you want rewriting to be automatically performed, call @code{planner-timeclock-summary-insinuate} in your @file{.emacs} file. @end itemize @file{planner-timeclock-summary-proj.el} produces task / time breakdowns on plan pages. Reports are of the form: @example TASK 0 | duration TASK 1 | duration TOTAL | duration. @end example To use, add @code{(require 'planner-timeclock-summary)} to your @file{~/.emacs}. Call @code{planner-timeclock-summary-proj-current} from a project page. The report is inserted at the current position in the buffer. The function @code{planner-timeclock-summary-proj-section} does the same but the report is inserted inside a section called @samp{* Report}. @node schedule.el, , Timeclock, Scheduling and Time @comment node-name, next, previous, up @subsection @file{schedule.el} @cindex @file{planner-schedule.el}, using @cindex @file{schedule.el}, using Planner with @file{planner-schedule.el} allows you to project task completion time. Tasks should be of the form: @example #A0 _ 2h Do something #B0 _ 1h30m Do something #B0 _ 2d Do something #B0 _ 2w Do something #B0 _ 10s Do something s: seconds, m: minutes, h: hours, d: days, w: weeks @end example @file{schedule.el} is included with Planner in the @file{contrib} directory, but you can alternatively get it from @url{http://www.newartisans.com/johnw/Emacs/schedule.el} if desired. @file{schedule.el} provides a single Lisp function, @code{schedule-completion-time}. It takes an Emacs time object and a quantity of seconds. It returns an Emacs time object that represents when the given number of seconds will be completed, assuming that work can only be done during work hours. The available work hours are affected by several factors: @enumerate @item If @file{timeclock.el} is being used, the amount of time left in the current work day (@code{timeclock-workday-remaining}) (@pxref{Time Intervals, , , Emacs, GNU Emacs Manual}) @item The amount of time in each work day (@code{schedule-workday}) @item The definition of a work week (@code{schedule-week}) @item Any holidays defined in the Emacs calendar (@pxref{Holidays, , , Emacs, GNU Emacs Manual}) @item Any appointments in the Emacs diary (@pxref{Appointments, , , Emacs, GNU Emacs Manual}) @end enumerate Taking all of the ``block out'' periods into account, @code{schedule-completion-time} will compute when the given number of seconds will be done, based on your current definitions of time available. As an example, here's a function which, given a list of durations in seconds, will return a list of completion times starting from the current moment: @example (defun compute-completion-times (&rest durations) ``Compute completion times for a list of DURATIONS (in seconds).'' (let ((now (current-time))) (mapcar (function (lambda (dura) (setq now (schedule-completion-time now dura)))) durations))) @end example To call this function, do: @example (compute-completion-times 3600 7200 3600) @end example @subheading Keys @file{planner-schedule.el} defines the following keybindings: @kbd{C-c RET} is bound to @command{planner-schedule-show-end-project}. @kbd{C-c C-m} is also bound to @command{planner-schedule-show-end-project}. In XEmacs, @command{planner-schedule-show-end-project} is bound to @kbd{C-c C-T c-e} and @kbd{C-c C-S-t C-e}. @subheading Functions @file{planner-schedule.el} defines the following interactive functions: @defun planner-schedule-show-end-project Display the estimated project completion time. @end defun @file{schedule.el} does not define any interactive functions, or keybindings. @node Finances, Contacts and Conversations, Scheduling and Time, Managing Your Information @comment node-name, next, previous, up @section Finances @cindex finances Currently, Planner provides one module dedicated to tracking your finances. This module works with a program called Ledger. @menu * Ledger:: Personal finances: planner-ledger.el @end menu @node Ledger, , Finances, Finances @comment node-name, next, previous, up @subsection Ledger @cindex finances @cindex @file{planner-ledger.el}, using @cindex @file{ledger}, using Planner with @file{planner-ledger.el} provides integration between planner and John Wiegley's ledger accounting program, which can be found at @url{http://newartisans.com/johnw/ledger.tar.gz}. To use planner-ledger to insert a ledger balance overview and a list of pending transactions into planner day pages, make sure that your day page includes sections that match @code{planner-ledger-balance-regexp} and @code{planner-ledger-pending-regexp}. Example: @example * Tasks * Ledger ** Pending transactions * Notes @end example You can manually update ledger sections with the @command{planner-ledger-insert-maybe} command. You can also automatically update ledger sections with the following hook: @example (add-hook 'planner-goto-hook 'planner-ledger-insert-maybe) @end example You can create ledger entries from specially-formatted tasks using @command{planner-ledger-add-entry-from-task}. Tasks should be of the form @samp{payment due: payee, amount [comment]}. Example: @example #A1 _ payment due: foobar, $1000.00 some comment here #A2 _ payment due: baz, 1000.00 @end example @subheading Options @defopt planner-ledger-balance-accounts List of accounts to be included or excluded from the balance overview. @samp{+} includes all matching accounts, and @samp{-} excludes matching accounts. See the documentation for @command{ledger-run-ledger} for more details. @end defopt @defopt planner-ledger-balance-regexp Regular expression matching section for ledger balance. Do not store other data in this section, as it will be overwritten. @end defopt @defopt planner-ledger-pending-regexp Regular expression matching section for ledger balance. Do not store other data in this section, as it will be overwritten. @end defopt @defopt planner-ledger-payment-task-regexp Regular expression matching special ledger tasks. @end defopt @subheading Functions @defun planner-ledger-insert-maybe Update any ledger sections on the current page. @end defun @defun planner-ledger-add-entry-from-task Create a ledger entry based on the task at point. Task should match @code{planner-ledger-payment-task-regexp}. @end defun @node Contacts and Conversations, Tracking Research and Resources, Finances, Managing Your Information @comment node-name, next, previous, up @section Contacts and Conversations @cindex contacts @cindex conversations Planner has two modules available for keeping track of contact and conversation information. The first uses the Big Brother Database (BBDB), and the second uses Emacs Relay Chat (ERC). BBDB is a full contact database. ERC is a client for chatting online on Internet Relay Chat (IRC) networks. The ERC module for Planner will help you keep track of online conversations you have if you use ERC for those conversations, but does not by itself store contact information other than the time you had the conversation, the network and channel you were on when you had it, and maybe who you had it with. If you are looking for a way to manage your full address book, then @file{planner-bbdb.el} in combination with BBDB is what you are looking for. @menu * BBDB:: Contacts: planner-bbdb.el * Emacs Relay Chat:: Internet Relay Chat: planner-erc.el @end menu @node BBDB, Emacs Relay Chat, Contacts and Conversations, Contacts and Conversations @comment node-name, next, previous, up @subsection BBDB @cindex @file{planner-bbdb.el}, using @cindex BBDB, using Planner with @file{planner-bbdb.el} allows you to refer to your contacts easily from within a planner page. @inforef{Top, the BBDB Manual, bbdb}. @samp{[[bbdb://Sacha.*Chua][Sacha]]}, for example, will be linked to the blog, web or net fields of the first matching BBDB record. @file{planner-bbdb.el} does not define any interactive functions, or keybindings. @node Emacs Relay Chat, , BBDB, Contacts and Conversations @comment node-name, next, previous, up @subsection Emacs Relay Chat @cindex @file{planner-erc.el}, using @cindex ERC, using Planner with @cindex Emacs Relay Chat, using Planner with @cindex IRC, using Planner with @cindex Internet Relay Chat, using Planner with To use planner-erc, place @file{planner-erc.el} in your load path and add this to your @file{.emacs} (or @file{_emacs}): @example (require 'planner-erc) @end example IRC URLs may be of the following forms. @example irc://server/nick,isnick irc://server/#channel irc://server @end example Annotations will be in the following forms. @example [[irc://server/nick,isnick][Chat with nick on server#channel]] [[irc://server/nick,isnick][Chat with nick on server]] [[irc://server/#channel][Chat on server#channel]] [[irc://server][Chat on server]] @end example @file{planner-erc.el} does not define any interactive functions, or keybindings. @node Tracking Research and Resources, Tracking Development, Contacts and Conversations, Managing Your Information @comment node-name, next, previous, up @section Tracking Research and Resources Planner provides three modules for keeping track of information involving three specific tools: w3m, BibTeX, and @file{bookmark.el}. @menu * W3m:: Web browser: planner-w3m.el * BibTeX:: Bibliographies: planner-bibtex.el * Bookmark:: Bookmarks: planner-bookmark.el @end menu @node W3m, BibTeX, Tracking Research and Resources, Tracking Research and Resources @comment node-name, next, previous, up @subsection W3m @cindex @file{planner-w3m.el}, using @cindex w3m, using Planner with This module allows you to create tasks from a w3m buffer. @file{planner-w3m.el} does not define any interactive functions, or keybindings. @node BibTeX, Bookmark, W3m, Tracking Research and Resources @comment node-name, next, previous, up @subsection BibTeX @cindex @file{planner-bibtex.el}, using BibTeX URLs are of the form @samp{bibtex:file/name:key}. @file{planner-bibtex.el} does not define any interactive functions. @node Bookmark, , BibTeX, Tracking Research and Resources @comment node-name, next, previous, up @subsection Bookmark @cindex bookmarks @cindex @file{bookmark.el}, using Planner with @cindex @file{planner-bookmark.el}, using @file{planner-bookmark.el} uses the @file{remember} package to create a note whenever you create a bookmark (@pxref{Bookmarks, Bookmarks,, emacs}) For more information about @file{remember}, please check out @itemize @item @uref{http://www.emacswiki.org/cgi-bin/wiki/RememberMode} - EmacsWiki.org page @end itemize Configure remember according to the instructions in @file{remember-planner.el} so that notes are saved to your planner pages. @defopt planner-bookmark-take-note-after-set-bookmark-flag Non-nil means show a @code{remember} buffer after setting a new bookmark. @end defopt When you create a bookmark, Emacs will open a buffer for your notes. @kbd{C-c C-c} saves the buffer to today's page. If you don't want to save a note, you can kill the buffer. Bookmark URLs are of the form @samp{bookmark://bookmark-name}. @file{planner-bookmark.el} does not define any interactive functions. @node Tracking Development, , Tracking Research and Resources, Managing Your Information @comment node-name, next, previous, up @section Tracking Development @cindex version control, using Planner with Planner has three modules geared toward programmers. Two modules deal with version control and integrating information from those projects into the planner page. One module deals with the Gnats bug-tracking system. @menu * Log Edit:: Changelogs: planner-log-edit.el * PSVN:: svn changesets: planner-psvn.el * XTLA:: TLA changesets: planner-xtla.el * Gnats:: Gnats: The GNU bug reporting system @end menu @node Log Edit, PSVN, Tracking Development, Tracking Development @comment node-name, next, previous, up @subsection Log Edit @cindex cvs, using Planner with @cindex @file{planner-log-edit.el}, using @cindex version control, using Planner with This module allows you to automatically record CVS (and VC) commits in today's page. You can load the module with @code{(require 'planner-log-edit)}. When you load the module, @code{planner-log-edit-add-note} will be added to @code{log-edit-done-hook}. A note containing the text of the commit and optionally a list of modified files will be added to today's page if you use the the Emacs version control interface. (@pxref{Version Control, , , Emacs, GNU Emacs Manual}) @subheading Options @defopt planner-log-edit-include-files-flag Non-nil means include a list of committed files in the note. @end defopt @defopt planner-log-edit-notice-commit-function Non-nil means include a list of committed files in the note. If you want to enable this feature for some projects but not for others, set this to a function that returns t only for the commits you want to note. @end defopt @file{planner-log-edit.el} does not define any interactive functions. @node PSVN, XTLA, Log Edit, Tracking Development @comment node-name, next, previous, up @subsection PSVN @cindex PSVN @cindex @file{planner-psvn.el}, using @cindex Subversion, integration with This module enables you to refer to your Subversion (svn) changesets easily from within a Planner page, and to have your svn commits recorded automatically as notes in your planner. You must also have @file{psvn.el}, which is often packaged with Subversion in GNU/Linux distributions. You can then load the module by adding @code{(require 'planner-psvn)} to your @file{~/.emacs}. Once the module is loaded, Planner will pick up annotation information from any psvn *svn-log-view* buffer. If you create a task or note while in such a buffer, that task will have a hyperlink you can follow to return to the changeset later. These hyperlinks are of the form @samp{psvn://http://my.svn-repos.at/svn/project1/trunk@@39} Additionally, you can have notes for your commits automatically generated. Set @var{planner-psvn-log-edit-notice-commit-function} to t to enable this. By default, these commit notes will include a list of the files modified. If you would prefer to have this list not included, set @var{planner-psvn-log-edit-include-files-flag} to nil. @node XTLA, Gnats, PSVN, Tracking Development @comment node-name, next, previous, up @subsection XTLA @cindex XTLA @cindex @file{planner-xtla.el}, using This module allows you to refer to changesets in Tom Lord's Arch (tla) version control system. You can load the module with @code{(require 'planner-xtla)}. When you load the module, you can create tasks from XTLA windows by positioning point on a revision. XTLA URLs are of the form @samp{xtla://miles@@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-19} @file{planner-xtla.el} does not define any interactive functions. @node Gnats, , XTLA, Tracking Development @comment node-name, next, previous, up @subsection Gnats @cindex Gnats @cindex @file{planner-gnats.el}, using @cindex bug reports, tracking @file{planner-gnats.el} provides support for the GNU problem report management system Gnats. This module allows you to refer to problem reports using hyperlinks. Configure your Emacs for Gnats access, then add @samp{(require 'planner-gnats)} to your @file{.emacs}. You can then create tasks from Gnats edit or view buffers. To add keybindings to Gnats, use @samp{(planner-gnats-insinuate)}. Gnats URLs are of the form @samp{gnats:pr-number}. @file{planner-gnats.el} does not define any interactive functions. @node Advanced Configuration, Reference Material, Managing Your Information, Top @comment node-name, next, previous, up @chapter Advanced Configuration @cindex configuration, advanced @menu * Customizing Your Day Pages:: Change your templates * Variables to Customize:: Change various aspects of Planner behavior * Ideas for Other Keybindings:: Add to and change the default keybindings @end menu @node Customizing Your Day Pages, Variables to Customize, Advanced Configuration, Advanced Configuration @comment node-name, next, previous, up @section Customizing Your Day Pages With the variable @code{planner-day-page-template}, you can define how you want any newly created day planner pages to look. You might want to include a section for your diary entries. For how to do this, see @ref{Diary}. You can add interactive Lisp buttons with the @file{planner-lisp.el} module. (@pxref{Interactive Lisp}) Your @code{planner-day-page-template} can also include @samp{||} tags. For more complex day pages, you can set @code{planner-day-page-template} to a function that will be called from an empty day page buffer. The function should initialize the contents of the day page. @node Variables to Customize, Ideas for Other Keybindings, Customizing Your Day Pages, Advanced Configuration @comment node-name, next, previous, up @section Variables to Customize @cindex customize, variables to @cindex variables, customization of @cindex configuration, advanced, variables You can use Customize (@kbd{M-x customize-group RET planner RET}) to set user variables. Other user options are: @vindex planner-use-day-pages @defopt planner-use-day-pages If you really don't like day pages, you can set this variable to nil and you won't be prompted for dates for tasks (and notes, if using @file{remember-planner}). @end defopt @vindex planner-use-plan-pages @defopt planner-use-plan-pages If you really don't like plan pages, you can set this variable to nil and you won't be prompted for plan pages for tasks (and notes, if using @file{remember-planner}). @end defopt @vindex planner-mode-hook @defopt planner-mode-hook List of functions to run after @code{planner-mode} is initialized. @end defopt @vindex planner-tasks-file-behavior @defopt planner-tasks-file-behavior This variable controls what happens to files Planner opens by itself. If your tasks are associated with plan pages, the plan pages are updated whenever a task is rescheduled. This could lead to a lot of open buffers as Planner applies updates to all linked files. By default, Planner is configured to do nothing. A value of @samp{save} means save but do not close buffers, and a value of @samp{nil} means do not save any of the buffers. @end defopt @vindex planner-add-task-at-end-flag @defopt planner-add-task-at-end-flag This variable controls where new tasks are created. Non-nil means create tasks at the bottom of the first task block. If you set this to non-nil, new tasks will be listed in order of creation (oldest). Tasks carried over from previous days will appear at the bottom of the list. Nil means create tasks at the top of the first task block. Carried-over tasks and newly created tasks are prominently placed on top of the list of tasks for the day. @end defopt @vindex planner-default-page @defopt planner-default-page Default page for created tasks. This is used as the initial value for tasks. After you create a task, it will be set to the previous page used. @end defopt @vindex planner-hide-task-status-when-highlighting @defopt planner-hide-task-status-when-highlighting Font-locking for tasks may be enough for you to determine status and priority. Set this to non-nil if you want to hide the status marker and rely on font-locking instead. @end defopt @vindex planner-create-task-hook @defopt planner-create-task-hook Functions run after creating a task. @code{planner-id} hooks into this. @end defopt @vindex planner-expand-name-favor-future-p @defopt planner-expand-name-favor-future-p If non-nil, partial dates (ex: @kbd{2} or @kbd{5.2}) are completed to dates in the future instead of using the current year and month. @end defopt @vindex planner-task-dates-favor-future-p @defopt planner-task-dates-favor-future-p Like @code{planner-expand-name-favor-future-p}, but only for tasks. @end defopt @vindex planner-publish-dates-first-p @defopt planner-publish-dates-first-p Non-nil means list day pages first in the planner index. @end defopt @node Ideas for Other Keybindings, , Variables to Customize, Advanced Configuration @comment node-name, next, previous, up @section Ideas for Other Keybindings @cindex keybindings, customization of @cindex configuration, advanced, keybindings @cindex customize, keybindings to By default and for backward compatibility, the following operations do not have keybindings, and are only accessible from the Planner menu: @itemize @bullet @item @code{planner-copy-or-move-region} @item @code{planner-delete-task} @item @code{planner-task-delegated} @item @code{planner-task-pending} @item @code{planner-task-open} @item @code{planner-renumber-tasks} @end itemize You may find it easier to install keybindings for those operations by inserting the following in your @file{.emacs} (or @file{_emacs}). Note: This changes some of the default keybindings for Planner. @example (planner-install-extra-task-keybindings) @end example If you install the extra task keybindings, your keybindings will include: @itemize @bullet @item @kbd{C-c C-t} will be unbound from the default and will serve as the prefix for the other task keybindings. @item @kbd{C-c C-t C-t}: @code{planner-create-task-from-buffer}. @item @kbd{C-c C-t C-k}: @code{planner-delete-task}. @item @kbd{C-c C-t C-u}: @code{planner-update-task}. @item @kbd{C-c C-t C-c}: @code{planner-copy-or-move-task}. @item @kbd{C-c C-t C-S-c}: @code{planner-copy-or-move-region}. @item @kbd{C-c C-t C-x}: @code{planner-task-done}. @item @kbd{C-c C-t C-S-x}: @code{planner-task-cancelled}. @item @kbd{C-c C-t C-d}: @code{planner-task-delegated}. @item @kbd{C-c C-t C-p}: @code{planner-task-pending}. @item @kbd{C-c C-t C-o}: @code{planner-task-in-progress}. @item @kbd{C-c C-t C-r}: @code{planner-raise-task}. @item @kbd{C-c C-t C-l}: @code{planner-lower-task}. @item @kbd{C-c C-t C-n}: @code{planner-renumber-tasks}. @end itemize Other keybindings can be configured by adding this to your @file{.emacs} (or @file{_emacs}): @example (planner-install-extra-context-keybindings) @end example This will set up the following keybindings: @itemize @bullet @item @kbd{shift up} @code{planner-move-up} @item @kbd{shift down} @code{planner-move-down} @item @kbd{shift right} @code{planner-jump-to-link} @end itemize @node Reference Material, Getting Help, Advanced Configuration, Top @comment node-name, next, previous, up @chapter Reference Material @menu * Keeping Track of Time:: * Other Interactive Functions:: * Planner Keybindings:: Default keybindings for Planner * Sample Configuration Files:: @end menu @node Keeping Track of Time, Other Interactive Functions, Reference Material, Reference Material @section Keeping Track of Time One of the coolest things you can do with Planner is keep track of how much time you spend not only on projects but even on particular tasks. @file{planner-timeclock.el} makes it as easy and natural as marking a task as in progress, postponed, or done. This can help you determine just how much time you spend working each day. If you add estimates to your task descriptions, you'll also be able to use this information to improve your time estimation skills. For example, I had converted the TODO my teammate sent me into entries in my JapanProject plan page, and before starting my work I came up with rough estimates of the time it would take me to do the tasks. I also marked which tasks I felt were best suited for my coworker so that he could get started without worrying about conflicts. I like working on little tasks first, so I estimated the time it would take me to complete each task and sorted by my estimates using the @code{sort} command and some cutting and pasting. Then the fun began. I wanted to see if I could match my estimates. Before I started working on a task, I used @kbd{C-c TAB} to mark it @code{in progress} and start the clock. If I decided to work on something else, I used @kbd{C-c TAB} to clock out of the previous task and clock into the new one. When I finished it, I used @kbd{C-c C-x} (@code{planner-task-done}) to mark it completed and automatically clock out. This is not yet done for cancelled tasks, so I clocked out of those manually with @kbd{C-c C-o} (@code{timeclock-out}). I also clocked out whenever I caught myself being distracted so that the totals wouldn't include the time I spent chatting on #emacs or checking out del.icio.us links. =) At the end of the day, I used @code{planner-timeclock-summary-show-range-filter} to show me the time elapsed for all of the tasks I'd worked on over the past two days. Here's the report for that project, edited to reflect how it looks on my screen and annotated with comments: @example Timeclock summary report for 2004.12.28 - 2004.12.29 Project | Time| Ratio| Task JapanProject| 0:23:17| 3.6%| Translate javadoc comment for Messages.java | 0:33:48| 5.3%| Translate javadoc comment for LoginAction.java | 1:54:07| 17.8%| Study Struts in Japanese | 0:46:08| 7.2%| Add javadoc tags for input, output and forwards | 1:03:48| 9.9%| Help review code | 0:04:14| 0.7%| Import todo list | 0:00:37| 0.1%| 2min Fix Menu Action's unnecessary code - delegated | 0:01:01| 0.2%| 2min Remove unnecessary list in UserRemoveSetupAction - cancelled | 0:02:10| 0.3%| 2min Remove hard-coded database path from MenuAction | 0:02:46| 0.4%| 30min Create a superclass for our action classes that handles initialization of database and handling of privileges - remove all privilege handling in logic classes. ... | 0:07:32| 1.2%| 5min Add a method that returns the validity of a user in MUserPeer. | 0:08:28| 1.3%| 5min Fix indentation | 0:03:52| 0.6%| 10min Fix UserPeer so that it doesn't get null pointer exceptions | 0:04:34| 0.7%| 5min Add current password field in user_modify page | 0:21:56| 3.4%| 15min Make a super class for our service classes that will receive the database connection. (cancelled) | 0:06:05| 0.9%| 10min Remove hard-coded constants from the Logic classes | 0:10:55| 1.7%| 10min Move logic from UserBean.checkPassword to UserListLogic | 0:01:20| 0.2%| 20min Guard against null pointer exceptions in peer classes | 0:04:57| 0.8%| 10min Instead of displaying uneditable data with bean:write, just disable the html:text element | 0:25:03| 3.9%| 10min Deploy 10:00 version | 0:04:46| 0.7%| 5min Separate the configuration file of database and system into another uninternationalized property file. | 2:09:48| 20.2%| 1h Decide on a naming convention for localized messages and update files | 0:00:07| 0.0%| 20min Explain what is happening in UserModifyAction's nested ifs - pending | 1:50:23| 17.2%| 2h Write Javadoc comments in English and Japanese to explain bean structure | 0:04:19| 0.7%| 2h Write Javadoc comments in English and Japanese to explain peer operations (pending) | 0:05:40| 0.9%| 20min Make a factory class for the database - pending Total: | 10:41:41|100.0%| Day began: 13:03:58, Day ended: 20:51:46 Time elapsed: 31:47:48, Time clocked: 10:41:41 Time clocked ratio: 33.6% @end example The time record isn't perfect. I cancelled some tasks after thinking about them a little and did some tasks simultaneously. Sometimes I didn't notice that I was getting distracted, too. Still, having all of that time information neatly summarized made me realize a number of things. First, I goof off much less when I have a nice, broken-down task list in front of me. There's just something about knowing there's a five- or ten-minute hack you can get out of the way. I found myself looking forward to getting to the next task just to see if I could make my estimate. That said, seeing a five-minute task stretch and stretch due to unforeseen problems did make me a little nervous. I should probably just make generous estimates so that I don't end up with bugs because of haste. Second, I don't goof off as much as I thought I did, although there's still room for improvement. Yesterday's workday was 9:00 - 12:00, 1:00 - 5:30--7.5 hours. Today was the last day of work, so cleaning and celebration interrupted my hacking at around 3:00--5 hours of work. According to my task list, 10:41/12:30 was productive work. Hmm. 1:49 hours unclocked time when I was thinking or goofing off. planner-timeclock-summary-show for today reveals that I actually clocked 5:30 today, which means the goofing off happened yesterday. That makes sense; I remember a pretty long unclocked segment recuperating from Japanese overload. (This was before we came up with the task list.) Third, keeping track of time is way, way cool even if you don't bill anyone for your time. Like the idea? It's easy to try out. Just add @example (require 'planner-timeclock) (require 'planner-timeclock-summary) @end example to your ~/.emacs. If you want to try it out now, eval those statements in your Emacs session. After that, simply use @kbd{C-c TAB} to ``clock in'' a task before you start working on it and @kbd{C-c C-x} (@code{planner-task-done}) to mark it completed. @kbd{M-x planner-task-pending} also clocks out the current task if it was clocked in. To see a summary of how you spent your day, check out the different functions in @file{planner-timeclock-summary}. See @ref{Timeclock} for more details. Happy hacking! @node Other Interactive Functions, Planner Keybindings, Keeping Track of Time, Reference Material @comment node-name, next, previous, up @section Other Interactive Functions With @file{planner.el} loaded, you can use any of the functions in this section by typing @kbd{M-x} followed by the name of the function. Many of these functions are also bound to keys. For a list of Planner keybindings, see @ref{Planner Keybindings}. They are listed in no particular order. @file{planner.el} defines the following interactive functions: @defun planner-create-high-priority-task-from-buffer Create a high priority task based on this buffer. Do not use this in LISP programs. Instead, set the value of @var{planner-default-task-priority} and call @code{planner-create-task} or @code{planner-create-task-from-buffer}. @end defun @defun defun planner-create-medium-priority-task-from-buffer Create a medium-priority task based on this buffer. Do not use this in LISP programs. Instead, set the value of @var{planner-default-task-priority} and call @code{planner-create-task} or @code{planner-create-task-from-buffer}. @end defun @defun planner-create-low-priority-task-from-buffer Create a high-priority task based on this buffer. Do not use this in LISP programs. Instead, set the value of @var{planner-default-task-priority} and call @code{planner-create-task} or @code{planner-create-task-from-buffer}. @end defun @defun planner-install-extra-context-keybindings Install extra context-sensitive keybindings. These keybindings conflict with @file{windmove.el}, but might be useful. @end defun @defun planner-narrow-to-section section &optional create Widen to the whole page and narrow to the section labelled @var{section}. If @var{create} is non-nil and the section is not found, the section is created. Return non-nil if @var{section} was found or created. @end defun @defun planner-save-buffers Save all planner-mode buffers. @end defun @defun planner-seek-to-first section Positions the point at the specified @var{section}, or @samp{Tasks} if not specified. @end defun @defun planner-save-buffers Save all planner buffers. @end defun @defun planner-calendar-insinuate This hooks Planner into Emacs Calendar (@pxref{Calendar/Diary, , , Emacs, GNU Emacs Manual}). It adds special planner key bindings to @code{calendar-mode-map}. After this function is evaluated, you can use the following planner-related keybindings in @code{calendar-mode-map}: @table @kbd @item n Jump to the planner page for the current day. @item N Display the planner page for the current day. @end table @end defun @defun planner-kill-calendar-files Remove planner files shown from Calendar (@pxref{Calendar/Diary, , , Emacs, GNU Emacs Manual}). @end defun @defun planner-calendar-goto Goto the plan page corresponding to the calendar date (@pxref{Calendar/Diary, , , Emacs, GNU Emacs Manual}). @end defun @defun planner-calendar-show Show the plan page for the calendar date under point in another window (@pxref{Calendar/Diary, , , Emacs, GNU Emacs Manual}). @end defun @defun planner-calendar-select Return to @code{planner-read-date} with the date currently selected (@pxref{Calendar/Diary, , , Emacs, GNU Emacs Manual}). @end defun @defun planner-jump-to-link Jump to the item linked to by the current item. @end defun @defun planner-move-up Move a task up. You can use this to indicate that you will do a task before another one. On a note, go to the previous note. On a headline, go to the previous headline of the same depth. @end defun @defun planner-move-down Move down. You can use this to indicate that you will do a task after another one. On a note, go to the next note. On a headline, go to the next headline of the same depth. @end defun @node Planner Keybindings, Sample Configuration Files, Other Interactive Functions, Reference Material @comment node-name, next, previous, up @section Planner Keybindings @cindex keybindings, list In order to refresh and renumber all of your tasks according to their actual order in the buffer, simply save the file or call @kbd{M-x planner-renumber-tasks}. Here is a summary of the keystrokes available: @table @kbd @item M-x plan Begin your planning session. This goes to the last day for which there is any planning info (or today if none), allowing you to review, and create/move tasks from that day. @item C-c C-u Move a task up. @item C-c C-d Move a task down. @item C-c C-s Mark the task as in progress or delegated. @item C-c C-x Mark the task as finished. @item C-c C-t Create a task associated with the current Wiki page. If you are on the opening line of a Note entry, it is assumed that the note itself is the origin of the task. @item C-c C-c Move or copy the current task to another date. If the current task is an original (meaning you are in the buffer where's defined, hopefully a planning page) then it will be copied, and the original task will also now point to the copy. If the current task is a copy, it will just be moved to the new day, and the original task's link will be updated. @item C-c C-n Jump to today's task page. If you call @code{(planner-calendar-insinuate)}, typing @kbd{n} in the Emacs calendar (@pxref{Calendar/Diary, , , Emacs, GNU Emacs Manual}) will jump to today's task page. @item C-c C-x @code{planner-task-done} @item C-c C-z @code{planner-task-in-progress} @item C-c C-d @code{planner-lower-task} @item C-c C-u @code{planner-raise-task} @item C-c C-c @code{planner-copy-or-move-task} @item C-c C-t @code{planner-create-task-from-buffer} @item C-c C-j This is a prefix command. @item C-c C-n @code{planner-goto-today} @item C-c C-j C-r @code{planner-goto-most-recent} @item C-c C-j C-t @code{planner-goto-tomorrow} @item C-c C-j C-y @code{planner-goto-yesterday} @item C-c C-j C-j @code{planner-goto-today} @item C-c C-j C-n @code{planner-goto-next-daily-page} @item C-c C-j C-p @code{planner-goto-previous-daily-page} @item C-c C-j C-d @code{planner-goto} @end table @node Sample Configuration Files, , Planner Keybindings, Reference Material @comment node-name, next, previous, up @section Sample Configuration Files @cindex configuration, sample This section includes some sample configuration files. This way, once you've got the hang of the basics, you can see some different, more advanced, setups. There is no One True Way to plan. Every person is different. We hope you'll find a good starting point among the example configurations below. If what you want to do does not perfectly fit under one of these examples, please post a description of the way you plan to our mailing list (@pxref{Getting Help}). We look forward to helping you customizing planner to fit your needs. @menu * File Organization:: * Bare-Bones Planning:: * Bare-Bones Planning with Plan Pages:: * Tasks on Plan Pages with Some Day Pages:: * Hierarchical Tasks:: @end menu @node File Organization, Bare-Bones Planning, Sample Configuration Files, Sample Configuration Files @subsection File Organization @itemize @item @strong{Tasks, schedule and notes on day pages.} By default, tasks, schedule entries and notes are filed on day pages. This makes it easy for you to see all the entries relevant to a single day without becoming overwhelmed with information. Unfinished tasks are carried over to the next day when you use @kbd{M-x plan}, so it's always kept up to date. Completed tasks are left on the day page you finished them on, which helps when reviewing one's progress and writing accomplishment reports. @item @strong{Cross-referenced with plan pages.} You can associate your tasks with projects either when you create the task or later, with @kbd{M-x planner-replan-task}. This makes it easy for you to see all the information associated with a particular project. If you use RememberMode to create notes, you will also be able to associate notes with a plan page. @item @strong{Just plan pages.} If your tasks don't usually have dates, you can turn day pages off by customizing @code{planner-use-day-pages}. If so, then all of your tasks and notes will be stored on the WelcomePage and/or a plan page. @end itemize @node Bare-Bones Planning, Bare-Bones Planning with Plan Pages, File Organization, Sample Configuration Files @subsection Bare-Bones Planning You can keep all of your tasks, notes and schedules in a single file: WelcomePage. This is good for people who are used to storing all of their information in a flat text file. By storing your information in planner, you'll be able to take advantage of automatic hyperlinking to files and other resources. You can also sort your tasks by priority and status. To set your system up for bare-bones planning, set the @code{planner-use-day-pages} variable to nil before loading planner. For example, you can put this in your @file{~/.emacs} (or @file{_emacs}): @example (setq planner-use-day-pages nil) (setq planner-default-page nil) (require 'planner) @end example When you create a task or note, planner will not prompt you for a date. If you press @key{RET} when prompted for a plan page, it will accept the default of nil, so no other plan pages will be used. All of your data will be kept in one file, which can then be easily backed up. You can use commands like @command{planner-create-task-from-buffer} to create tasks, or you can type tasks in manually. You can edit or delete anything in the page without having to update other files. @node Bare-Bones Planning with Plan Pages, Tasks on Plan Pages with Some Day Pages, Bare-Bones Planning, Sample Configuration Files @subsection Bare-Bones Planning with Plan Pages When you create a task or note, Planner.el can copy this to a plan page. Plan pages allow you to see an overview of all the data for a project. For convenience, the @command{planner-create-task-from-buffer} command prompts you for a plan page when you create a task. @node Tasks on Plan Pages with Some Day Pages, Hierarchical Tasks, Bare-Bones Planning with Plan Pages, Sample Configuration Files @subsection Tasks on Plan Pages with Some Day Pages If most of your tasks are associated with plan pages but you want to schedule some tasks on day pages, you can leave day pages on (default) and then write a function that turns off day pages. For example, the following code snippet turns off day pages for task creation from buffers. @example (require 'planner) (defun my-planner-create-task-from-buffer () "Call `planner-create-task-from-buffer', but without dates." (interactive) (let ((planner-use-day-pages nil)) (call-interactively 'planner-create-task-from-buffer))) @end example @node Hierarchical Tasks, , Tasks on Plan Pages with Some Day Pages, Sample Configuration Files @subsection Hierarchical Tasks @cindex hierarchical tasks @cindex tasks, hierarchy of You can use @file{allout.el} or other modes for outlining to support hierarchical tasks in plan pages. No special support is needed. Tasks created by @command{planner-create-task-from-buffer} and @code{planner-create-task} are created in the @samp{* Tasks} section. If @code{planner-add-task-at-end-flag} is non-nil, tasks are added to the end of the first task block, else they are added to the beginning. You can then copy and paste tasks into your preferred hierarchy. Blank lines delimit blocks of tasks upon which automatic sorting is performed. You can also type in tasks manually. You may find this approach faster when you are comfortable with planner. For example, a @file{LearnPlanner} plan page might contain the following lines: @example * Learn how to use planner.el ** Installation #C0 _ Decide where to put Planner #C0 _ Download the archives ** Configuration *** Load path #C0 _ Figure out how to add things to my load path #C0 _ Actually add it to my load path ... @end example If you create tasks for the finest level of detail available at the moment, you can schedule them onto day pages with @kbd{C-c C-c} (@command{planner-copy-or-move-task}). Then you can use @command{planner-jump-to-link} to switch between the day page and the plan page link. @node Getting Help, Acknowledgements, Reference Material, Top @comment node-name, next, previous, up @chapter Getting Help @cindex help, getting @cindex bugs, reporting After you have read this guide, if you still have questions about Planner, or if you have bugs to report, there are several places you can go. Planner has an official website at @url{http://www.emacswiki.org/cgi-bin/wiki/PlannerMode}. It is a collaborative wiki. Bugs may be reported using the Planner Bug-Tracker at @url{http://gna.org/bugs/?group=planner-el}. Planner has three mailing lists. @table @samp @item planner-el-announce Low-traffic list for planner-related announcements. You can join this mailing list (@email{planner-el-announce@@gna.org}) using the subscription form at @url{http://mail.gna.org/listinfo/planner-el-announce/}. This mailing list is also available via Gmane (@url{http://gmane.org/}). The group is called @samp{gmane.emacs.planner.announce}. @item planner-el-discuss Discussion, bugfixes, suggestions, tips, and the like for Planner. This mailing list also includes the content of planner-el-announce. You can join this mailing list (@email{planner-el-discuss@@gna.org}) using the subscription form at @url{http://mail.gna.org/listinfo/planner-el-discuss/}. This mailing list is also available via Gmane with the identifier @samp{gmane.emacs.planner.general}. @item planner-el-logs Log messages for commits made to Planner. You can join this mailing list (@email{planner-el-logs@@gna.org}) using the subscription form at @url{http://mail.gna.org/listinfo/planner-el-logs/}. This mailing list is also available via Gmane with the identifier @samp{gmane.emacs.planner.scm}. @item planner-el-cvs Generated bug reports for Planner. You can join this mailing list (@email{planner-el-cvs@@gna.org}) using the subscription form at @url{http://mail.gna.org/listinfo/planner-el-cvs/}. This mailing list is also available via Gmane with the identifier @samp{gmane.emacs.planner.cvs}. @end table You can also contact the maintainer of Planner, John Sullivan, at @email{john@@wjsullivan.net}, but it is better to use the other options. You can explore the relevant sections of the EmacsWiki.org: @itemize @bullet @item @url{http://www.emacswiki.org/cgi-bin/wiki/PlannerMode} @item @url{http://www.emacswiki.org/cgi-bin/wiki/MuseMode} @item @url{http://www.emacswiki.org/cgi-bin/wiki/RememberMode} @end itemize You can visit the IRC Freenode channel @samp{#emacs}. Many of the contributors are frequently around and willing to answer your questions. There is an Orkut community called PlannerMode. For issues relating to this documentation, please contact John Sullivan at @email{john@@wjsullivan.net}. @node Acknowledgements, GNU General Public License, Getting Help, Top @comment node-name, next, previous, up @chapter Acknowledgements @itemize @item Maintainers @cindex maintainers @itemize @item 2006 John Sullivan volunteered to maintain Planner, and Michael Olson passed the maintainership on to him with the release of Planner 3.41. @item 2005 Michael Olson, Sacha Chua, and several others from the Planner community ported Planner to use Muse instead of emacs-wiki. Michael Olson became the maintainer of Planner. @item 2004 Damien Elmes handed EmacsWikiMode to Mark Triggs for a short period of time. Mark Triggs deferred to Sacha Chua as official maintainer of Planner. Sacha Chua volunteered to maintain RememberMode. Michael Olson became the maintainer of both emacs-wiki and Muse. @item 2003 Sacha Chua volunteered to maintain Planner. Damien Elmes volunteered to maintain EmacsWikiMode. @item 2001 John Wiegley wrote EmacsWikiMode and Planner. @end itemize @item Contributors @cindex contributors For a complete list of people who have helped out with Planner, please check out the @file{AUTHORS} file that is included with Planner. @end itemize @node GNU General Public License, Concept Index, Acknowledgements, Top @comment node-name, next, previous, up @appendix GNU GENERAL PUBLIC LICENSE @center Version 2, June 1991 @cindex GPL @cindex GNU General Public License @c The GNU General Public License. @center Version 3, 29 June 2007 @c This file is intended to be included within another document, @c hence no sectioning command or @node. @display Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @heading Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program---to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. @heading TERMS AND CONDITIONS @enumerate 0 @item Definitions. ``This License'' refers to version 3 of the GNU General Public License. ``Copyright'' also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. ``The Program'' refers to any copyrightable work licensed under this License. Each licensee is addressed as ``you''. ``Licensees'' and ``recipients'' may be individuals or organizations. To ``modify'' a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a ``modified version'' of the earlier work or a work ``based on'' the earlier work. A ``covered work'' means either the unmodified Program or a work based on the Program. To ``propagate'' a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To ``convey'' a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays ``Appropriate Legal Notices'' to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. @item Source Code. The ``source code'' for a work means the preferred form of the work for making modifications to it. ``Object code'' means any non-source form of a work. A ``Standard Interface'' means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The ``System Libraries'' of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A ``Major Component'', in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The ``Corresponding Source'' for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. @item Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. @item Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. @item Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. @item Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: @enumerate a @item The work must carry prominent notices stating that you modified it, and giving a relevant date. @item The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to ``keep intact all notices''. @item You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. @item If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. @end enumerate A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. @item Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: @enumerate a @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. @item Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. @item Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. @item Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. @end enumerate A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A ``User Product'' is either (1) a ``consumer product'', which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, ``normally used'' refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. ``Installation Information'' for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. @item Additional Terms. ``Additional permissions'' are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: @enumerate a @item Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or @item Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or @item Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or @item Limiting the use for publicity purposes of names of licensors or authors of the material; or @item Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or @item Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. @end enumerate All other non-permissive additional terms are considered ``further restrictions'' within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. @item Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. @item Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. @item Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An ``entity transaction'' is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. @item Patents. A ``contributor'' is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's ``contributor version''. A contributor's ``essential patent claims'' are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, ``control'' includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a ``patent license'' is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To ``grant'' such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. ``Knowingly relying'' means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is ``discriminatory'' if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. @item No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. @item Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. @item Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. @item Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. @item Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. @item Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. @end enumerate @heading END OF TERMS AND CONDITIONS @heading How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. @smallexample @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) @var{year} @var{name of author} This program 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. This program 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 this program. If not, see @url{http://www.gnu.org/licenses/}. @end smallexample Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: @smallexample @var{program} Copyright (C) @var{year} @var{name of author} This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. This is free software, and you are welcome to redistribute it under certain conditions; type @samp{show c} for details. @end smallexample The hypothetical commands @samp{show w} and @samp{show c} should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an ``about box''. You should also get your employer (if you work as a programmer) or school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see @url{http://www.gnu.org/licenses/}. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. @node Concept Index, , GNU General Public License, Top @comment node-name, next, previous, up @unnumbered Index @printindex cp @bye planner-el/planner-erc.el000066400000000000000000000120431226462314700156520ustar00rootroot00000000000000;;; planner-erc.el --- ERC support for Planner, an organizer for Emacs ;; Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Filename: planner-erc.el ;; Keywords: hypermedia erc chat ;; Author: Sacha Chua ;; Description: Create tasks and notes based on IRC ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Place planner-erc.el in your load path and add this to your .emacs: ;; ;; (require 'planner-erc) ;; IRC URLs may be of the following forms. ;; ;; irc://server/nick,isnick or ;; irc://server/#channel or ;; irc://server ;; Annotations will be in the following forms. ;; ;; [[irc://server/nick,isnick][Chat with nick on server#channel]] ;; [[irc://server/nick,isnick][Chat with nick on server]] ;; [[irc://server/#channel][Chat on server#channel]] ;; [[irc://server][Chat on server]] ;;; Contributors: ;;; Code: (require 'planner) (require 'erc) (unless (boundp 'erc-server-announced-name) (message "ERC 5.1 or higher is required; please upgrade ERC")) (defvar planner-irc-regexp "\\`[ei]rc://\\([^:/\n]+\\)\\([^/\n]+\\)?\\(?:/\\([^,/\n]+\\)\\(.*\\)\\)?" "Regexp used to match IRC URLs.") ;;;###autoload (defun planner-erc-annotation-from-erc () "Return an annotation for the current line. This function can be added to `planner-annotation-functions'." (when (eq major-mode 'erc-mode) (if (erc-default-target) (if (erc-channel-p (erc-default-target)) (if (and (get-text-property (point) 'erc-parsed) (elt (get-text-property (point) 'erc-parsed) 1)) (let ((nick (car (erc-parse-user (elt (get-text-property (point) 'erc-parsed) 1))))) (planner-make-link (concat "irc://" erc-server-announced-name "/" (substring nick 1) ",isnick") (concat "Chat with " nick " on " erc-server-announced-name (erc-default-target)) t)) (planner-make-link (concat "irc://" erc-server-announced-name "/" (erc-default-target)) (concat "Chat on " erc-server-announced-name (erc-default-target)) t)) (planner-make-link (concat "irc://" erc-server-announced-name "/" (erc-default-target)) (concat "Chat with " (erc-default-target) " on " erc-server-announced-name) t)) (planner-make-link (concat "irc://" erc-server-announced-name) (concat "Chat on " erc-server-announced-name) t)))) ;;;###autoload (defun planner-erc-browse-url (url) "If this is an IRC URL, jump to it." (when (string-match planner-irc-regexp url) (let ((server (match-string 1 url)) (port (match-string 2 url)) (target (match-string 3 url)) (flags (match-string 4 url)) buffer-list) ;; find existing buffer (setq buffer-list (erc-buffer-filter (lambda nil (let ((server-buffer (erc-server-buffer))) (and server-buffer (string= server (with-current-buffer server-buffer erc-server-announced-name))))))) ;; switch to buffer or create new connection (if buffer-list (if (not (stringp target)) ;; assume that the car is always the server buffer (switch-to-buffer (car buffer-list)) (switch-to-buffer (or (catch 'found (dolist (buffer buffer-list) (when (string= target (buffer-name buffer)) (throw 'found buffer)))) (car buffer-list)))) (erc-select :server server :port port))) t)) (planner-add-protocol "[ei]rc://" 'planner-erc-browse-url 'identity) (add-hook 'planner-annotation-functions 'planner-erc-annotation-from-erc) (custom-add-option 'planner-annotation-functions 'planner-erc-annotation-from-erc) (provide 'planner-erc) ;;; planner-erc.el ends here planner-el/planner-experimental.el000066400000000000000000000066551226462314700176120ustar00rootroot00000000000000;;; planner-experimental.el --- Experimental functions for Emacs planner mode ;; Copyright (C) 2004, 2008 Free Software Foundation, Inc. ;; Author: Sacha Chua ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: (require 'planner) ;;; Code: ;;;_ + Searching (defun planner-search-notes-next-match () "Jump to the next matching entry. Call after `planner-search-notes.'" (interactive) (if (buffer-live-p (get-buffer planner-search-notes-buffer)) (progn (set-buffer planner-search-notes-buffer) (forward-line -1) (goto-char (planner-line-beginning-position)) (planner-follow-name-at-point)) (error "No current search."))) (defun planner-search-notes-previous-match () "Jump to the previous matching entry. Call after `planner-search-notes.'" (interactive) (if (buffer-live-p (get-buffer planner-search-notes-buffer)) (progn (set-buffer planner-search-notes-buffer) (forward-line 1) (goto-char (planner-line-beginning-position)) (planner-follow-name-at-point)) (error "No current search."))) ;;;_* Tasks (defun planner-remove-duplicates () "Remove duplicate tasks." (interactive) (goto-char (point-min)) (let ((today (planner-today)) (on-date (string-match planner-date-regexp (planner-page-name)))) (while (re-search-forward "^#[A-C][0-9]*\\s-+\\(.+\\)$" nil t) (save-excursion (let* ((task-info (planner-current-task-info)) (keep (planner-task-date task-info)) date found (start (match-beginning 0))) (goto-char (planner-line-beginning-position)) (save-excursion (unless on-date (while (planner-find-task task-info (point)) ;; Determine the most recent one (setq date (planner-task-date (planner-current-task-info))) (when (or (and (string< keep today) (string< keep date)) (string< date keep)) (setq keep date)) (forward-line 1)))) (while (planner-find-task task-info (point)) (if (string= keep (planner-task-date (planner-current-task-info))) (if found (delete-region (planner-line-beginning-position) (min (1+ (planner-line-end-position)) (point-max))) (setq found t) (forward-line 1)) (planner-delete-task)))))))) ;;;_* Local emacs vars. ;;;Local variables: ;;;allout-layout: (-1 0 : ) ;;;End: (provide 'planner-experimental) ;;; planner-experimental.el ends here planner-el/planner-export-diary.el000066400000000000000000000122571226462314700175370ustar00rootroot00000000000000;;; planner-export-diary.el --- Diary export for the Emacs Planner ;; Copyright (C) 2001, 2004, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2004, 2008 Xin Wei Hu (huxw AT knight DOT 6test DOT edu DOT cn) ;; Emacs Lisp Archive Entry ;; Filename: planner-export-diary.el ;; Keywords: hypermedia ;; Author: John Wiegley ;; Description: Use Emacs for life planning ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Use this package if you want to export diary entries from your ;; planner to diary files. Customize `planner-export-diary-file' ;; (default: ~/diary.planner). Add the following line to your ;; main `diary-file' (default: ~/diary): ;; ;; #include ~/diary.planner ;; ;; and then call M-x planner-export-diary-future whenever you want ;; future diary entries published. You can automatically publish ;; entries by adding either of the following to your .emacs: ;; ;; a) Publish future entries on startup ;; ;; (planner-export-diary-future) ;; ;; b) Publish future entries whenever you save a planner file ;; ;; (add-hook 'planner-mode-hook 'planner-export-diary-setup) ;;;_ + Contributors ;; Xin Wei Hu (huxw AT knight DOT 6test DOT edu DOT cn) did some work ;; on `planner-export-diary-future' and ;; `planner-export-diary-get-schedule-entries'. ;; Yann Hodique helped port this to Muse. ;;; Code: (require 'planner) (defvar planner-export-diary-file "~/diary.planner" "*Name of the file into which schedules are exported from planner. This file will be automatically overwritten every time planner entries are exported, so be careful.") (defvar planner-export-diary-number-of-days 3 "*Number of days to export diary appointments for.") ;;;###autoload (defun planner-export-diary-future () "Exports only `planner-export-number-of-days' days of entries. This function can be put into your `after-save-hook'." (interactive) (planner-export-diary (planner-today) (planner-calculate-date-from-day-offset (planner-today) (1- planner-export-diary-number-of-days)))) ;;;###autoload (defun planner-export-diary-setup () "Add `planner-export-diary-future' to `after-save-hook' in planner buffers. You can add this function to `planner-mode-hook'." (add-hook 'after-save-hook 'planner-export-diary-future nil t)) (defun planner-export-diary-get-schedule-entries (files) "Return a list containing the planner schedule entries in FILES. Entries in the returned list are of the form [DATE START END DATA]. FILES is an alist of planner pages and their filenames." (with-temp-buffer (cd (planner-directory)) (let ((list '()) start end data) (while (car files) (insert-file-contents (cdar files)) (goto-char (point-min)) (while (re-search-forward "^\\s-*\\([0-9]+:[0-9]+\\)\\s-*|\\s-*\\(.+\\)" nil t) (setq start (match-string 1)) (setq data (match-string 2)) (setq end nil) (when (string-match "\\([0-9]+:[0-9]+\\)\\s-*|\\s-*" data) (setq end (match-string 1 data)) (setq data (replace-match "" nil t data))) (setq list (cons (vector (caar files) start end data) list))) (setq files (cdr files)) (erase-buffer)) list))) (defun planner-export-diary-format-schedule-entries-for-diary (list) "Format LIST as diary entries. LIST should contain entries of the form [DATE START END DATA]." (mapconcat (lambda (item) (concat (let ((date (planner-filename-to-calendar-date (elt item 0)))) (format "%02d/%02d/%04d" (elt date 0) (elt date 1) (elt date 2))) " " (elt item 1) " " (elt item 3))) list "\n")) ;;;###autoload (defun planner-export-diary (&optional from to) "Exports all the schedules or the ones from FROM to TO (inclusive)." (interactive) (with-temp-file planner-export-diary-file (insert (planner-export-diary-format-schedule-entries-for-diary (planner-export-diary-get-schedule-entries (planner-get-day-pages from to)))))) (provide 'planner-export-diary) ;;; planner-export-diary.el ends here planner-el/planner-gnats.el000066400000000000000000000062411226462314700162200ustar00rootroot00000000000000;;; planner-gnats.el --- GNATS integration for the Emacs Planner ;; Copyright (C) 2005, 2008 Jeremy Cowgar (jeremy AT cowgar DOT com) ;; Author: Jeremy Cowgar (jeremy AT cowgar DOT com) ;; Keywords: planner, gnats ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; URL: http://www.gnu.org/software/gnats/ ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; GNATS is the GNU problem report management system (central database) ;; GNATS is a bug-tracking tool designed for use at a central "Support ;; Site". Users who experience problems use electronic mail to ;; communicate these problems to "maintainers" at that Support Site. ;; ;; Add ;; ;; (require 'planner-gnats) ;; ;; to your .emacs. You will then be able to call M-x ;; planner-create-task-from-buffer from Gnats edit or view buffers ;; with the correct annotation. ;; To add keybindings to Gnats, call (from .emacs) ;; ;; (planner-gnats-insinuate) ;; ;; URLs are of the form gnats:pr-number ;;; Todo:: ;; 1. The URL should really be something like ;; gnats:database/pr-number however, I'm not yet certian how to ;; handle all the possible variations to setup the correct server, for ;; instance, port number, user name, password. The password could then ;; get tricky, because what if the text file is stored in an unsecure ;; manner? ;; ;; So, right now this assumes your gnats is already setup for the ;; correct server, which will be the case for probably 90% of the ;; users. ;;; Code: (require 'planner) (require 'gnats) ;;;###autoload (defun planner-gnats-annotation-from-gnats () "If called from gnats-edit or gnats-view buffer, return an annotation. Suitable for use in `planner-annotation-functions'." (when (string-match "^\\*gnats-\\(edit\\|\\view\\)-\\(.+\\)\\*" (buffer-name)) (let ((pr-num (match-string 2 (buffer-name)))) (planner-make-link (concat "gnats:" pr-num) (concat "Gnats Bug: " pr-num) t)))) ;;;###autoload (defun planner-gnats-browse-url (url) "If this is a Gnats URL, view the pr (view-pr)." (when (string-match "\\`gnats:/*\\(.+\\)" url) (let ((pr-num (match-string 1 url))) (view-pr (string-to-number pr-num))) t)) (planner-add-protocol "gnats:/*" 'planner-gnats-browse-url nil) (custom-add-option 'planner-annotation-functions 'planner-gnats-annotation-from-gnats) (add-hook 'planner-annotation-functions 'planner-gnats-annotation-from-gnats) (provide 'planner-gnats) ;;; planner-gnats.el ends here planner-el/planner-gnus.el000066400000000000000000000243711226462314700160640ustar00rootroot00000000000000;;; planner-gnus.el --- Gnus integration for the Emacs Planner ;; Copyright (C) 2001, 2003, 2004, 2005, ;; 2006, 2007, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2004, 2008 Mario Domgörgen (kanaldrache AT gmx.de) ;; Author: John Wiegley ;; Keywords: planner, gnus ;; URL: http://www.emacswiki.org/cgi-bin/wiki/PlannerMode ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file adds annotations for Gnus messages. ;You will then be ;; able to use M-x planner-create-task-from-buffer to create tasks ;; from Gnus summary or message buffers with the correct annotation. ;; If you add ;; ;; (planner-gnus-insinuate) ;; ;; to your .emacs, you can also use 'C-c C-t' to create a task from a buffer. ;;; Contributors: ;; Daniel Neri (dne AT mayonnaise DOT net) fixed a few typos and ;; updated the commentary. ;; Mario Domgörgen (kanaldrache AT gmx DOT de) got this to work nicely ;; with multiple marked messages in Gnus summary buffers. ;; Sven Kloppenburg (kloppenburg AT informatik.tu-darmstadt.de) ;; provided a patch to use gnus-registry if loaded. ;; Magnus Henoch (mange AT freemail.hu) provided a patch to add space ;; after the author's name on newgroups. ;; Stefan Reichör fixed a problem with getting group names from Gnus. ;; Yann Hodique fixed a couple of typos. ;; Dale Smith helped determine the necessary changes for Emacs21 ;; support. ;;; Code: (require 'planner) (require 'gnus) (require 'gnus-msg) ;;;###autoload (defun planner-gnus-insinuate () "Hook Planner into Gnus. Adds special planner keybindings to the variable `gnus-summary-article-map'. From a summary or article buffer, you can type C-c C-t to call planner-create-task-from-buffer." (eval-after-load 'gnus-sum `(define-key gnus-summary-mode-map ,(kbd "C-c C-t") 'planner-create-task-from-buffer)) (eval-after-load 'gnus `(define-key gnus-article-mode-map ,(kbd "C-c C-t") 'planner-create-task-from-buffer))) (require 'gnus-sum) (defun planner-gnus-get-message-id (&optional article-number) "Return the message-id of the current message." (save-excursion (if (equal major-mode 'gnus-summary-mode) (let ((mhmi (mail-header-message-id (gnus-data-header (assq (or article-number (gnus-summary-article-number)) gnus-newsgroup-data))))) (if (nnheader-fake-message-id-p mhmi) (number-to-string article-number) mhmi)) ;; Refer to the article buffer (save-excursion (goto-char (point-min)) (let ((case-fold-search t)) (when (re-search-forward "^Message-ID:\\s-*\\(.+\\)" (point-max) t) (match-string 1))))))) (defun planner-gnus-get-address (&optional header) "Return the address of the sender of the current message. If HEADER is \"To\", return the recipient instead." (save-excursion (goto-char (point-min)) (let ((case-fold-search t)) (when (re-search-forward (concat "^" (or header "From") ":\\s-*\\(.+\\)") (point-max) t) (planner-match-string-no-properties 1))))) (defun planner-gnus-annotation-from-summary () "If called from a Gnus summary buffer, return an annotation. Suitable for use in `planner-annotation-functions'." (when (equal major-mode 'gnus-summary-mode) (let ((articles (gnus-summary-work-articles nil))) (planner-make-link (concat "gnus://" gnus-newsgroup-name "/" (mapconcat (lambda (article-number) (planner-gnus-get-message-id article-number)) (gnus-summary-work-articles nil) "\\|")) (if (= 1 (length articles)) (let ((headers (gnus-data-header (assq (car articles) gnus-newsgroup-data)))) (if (gnus-news-group-p gnus-newsgroup-name) (concat "Post " (if (and planner-ignored-from-addresses (string-match planner-ignored-from-addresses (mail-header-from headers))) "" (concat "from " (planner-get-name-from-address (mail-header-from headers)) " ")) "on " gnus-newsgroup-name) (concat "E-Mail " (if (and planner-ignored-from-addresses (mail-header-from headers) (string-match planner-ignored-from-addresses (mail-header-from headers)) (assq 'To (mail-header-extra headers))) ;; Mail from me, so use the To: instead (concat "to " (planner-get-name-from-address (cdr (assq 'To (mail-header-extra headers))))) ;; Mail to me, so use the From: (concat "from " (planner-get-name-from-address (mail-header-from headers))))))) (concat (number-to-string (length articles)) " E-Mails from folder " gnus-newsgroup-name)) t)))) (defun planner-gnus-annotation-from-message () "If called from a Gnus article, return an annotation. Suitable for use in `planner-annotation-functions'." (when (or (equal major-mode 'gnus-article-mode) (equal major-mode 'gnus-original-article-mode)) (gnus-copy-article-buffer) (with-current-buffer gnus-article-copy (let ((from (planner-gnus-get-address "From")) (newsgroups (planner-gnus-get-address "Newsgroups"))) (planner-make-link (concat "gnus://" gnus-newsgroup-name "/" (planner-gnus-get-message-id)) (if newsgroups (concat "Post " (if (and planner-ignored-from-addresses (string-match planner-ignored-from-addresses from)) "" (concat "from " (planner-get-name-from-address from) " ")) "on " newsgroups) (concat "E-Mail " (let ((to-addr (planner-gnus-get-address "To"))) (if (and planner-ignored-from-addresses from to-addr (string-match planner-ignored-from-addresses from)) (concat "to " (planner-get-name-from-address to-addr)) (concat "from " (planner-get-name-from-address from)))))) t))))) ;;;###autoload (defun planner-gnus-annotation () "Return an annotation from a Gnus summary or message buffer. Suitable for use in `planner-annotation-functions'. If you include this, you can omit `planner-gnus-annotation-from-summary' and `planner-gnus-annotation-from-message'." (or (planner-gnus-annotation-from-summary) (planner-gnus-annotation-from-message))) (defvar planner-gnus-group-threshold 10 "Number of messages to retrieve from groups. Raise this if you have problems browsing gnus URLs.") ;;;###autoload (defun planner-gnus-browse-url (url) "If this is a Gnus URL, jump to it." (when (string-match "\\`gnus://\\(.+\\)/\\(.+\\)" url) (let ((group (match-string 1 url)) (articles (match-string 2 url))) (when (featurep 'gnus-registry) (let ((reg-group (gnus-registry-fetch-group articles))) (when reg-group (if gnus-registry-use-long-group-names (setq group reg-group) (when (cadr (split-string group ":")) ;; group contains a : (setq group (concat (car (split-string group ":")) ":" reg-group))))))) ;; Don't automatically select an article, as that might mark ;; unread articles as read. (let ((gnus-auto-select-first nil)) (condition-case err (gnus-fetch-group group planner-gnus-group-threshold t group) (error (gnus-fetch-group group)))) (mapcar (lambda (article-id) (gnus-summary-goto-article article-id nil t)) (split-string articles "\\\\|")) (let ((articles (if (fboundp 'gnus-find-matching-articles) (gnus-find-matching-articles "message-id" articles) (gnus-summary-find-matching "message-id" articles nil nil t)))) (gnus-summary-limit articles) (gnus-summary-select-article)) t))) (fset 'planner-get-from 'planner-gnus-get-address) (fset 'planner-get-message-id 'planner-gnus-get-message-id) (custom-add-option 'planner-annotation-functions 'planner-gnus-annotation) (add-hook 'planner-annotation-functions 'planner-gnus-annotation) (planner-add-protocol "gnus://" 'planner-gnus-browse-url nil) (provide 'planner-gnus) ;;; planner-gnus.el ends here planner-el/planner-ical.el000066400000000000000000000125051226462314700160140ustar00rootroot00000000000000;;; planner-ical.el --- Import/Export planner tasks in the icalendar standard (RFC 2445) ;; Copyright (C) 2005, 2008 Chris Parsons ;; Emacs Lisp Archive Entry ;; Filename: planner-ical.el ;; Author: Chris Parsons ;; Maintainer: Chris Parsons ;; Keywords: planner, ical ;; URL: http://sacha.free.net.ph/notebook/wiki/PlannerMode.php ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This module allows you to export planner tasks and notes in the ;; icalendar format (RFC 2445). For a description of the standard, see ;; http://www.ietf.org/rfc/rfc2445.txt. ;; ;; In future, it is hoped that tasks will be importable also. ;; ;; Note that this is very early days - currently we only export VTODO ;; items from just one page. ;; ;; Usage: ;; ;; Call planner-ical-export-page and specify the page, or ;; planner-ical-export-this-page. This produces a buffer. Save it ;; somewhere. (require 'planner) (require 'icalendar) ;;; Code: ;;;_+ User variables (defgroup planner-ical nil "iCal (RFC 2445) support for planner.el." :prefix "planner-ical" :group 'planner) (defcustom planner-ical-export-buffer "*Planner iCal Export*" "Buffer name for iCal exports from `planner-ical-export'." :type 'string :group 'planner-timeclock-summary) (defun planner-ical-export-page (page &optional file) "Export PAGE's tasks in the Ical format. If FILE is non-nil, results are saved to that file. If FILE is nil, results are displayed in a `planner-ical-export-buffer'." (interactive (list (planner-read-name (planner-file-alist) "Enter the page to export: "))) (if file (with-temp-file file (planner-ical-export (if (listp page) page (list page)))) (switch-to-buffer (get-buffer-create planner-ical-export-buffer)) (erase-buffer) (planner-ical-export (if (listp page) page (list page))))) (defun planner-ical-export (pages) "Export the given plan page to iCalendar format. The result will be added to the current buffer." (let ((tasks (planner-extract-tasks pages)) result) (while tasks (when (not (string= (planner-task-status (car tasks)) "X")) (let* ((task (car tasks)) cat-list cat-list-no-dates (header (format "\nBEGIN:VTODO\nUID:emacs-planner-%x" (sxhash (planner-task-description task)))) (my-task-date (planner-task-date task)) (task-date (if my-task-date (planner-filename-to-calendar-date my-task-date) nil)) (task-categories (if (featurep 'planner-multi) (progn (setq cat-list (planner-multi-task-link-as-list task)) (setq cat-list-no-dates nil) (while cat-list (let ((cat (car cat-list))) (when (not (string-match planner-date-regexp cat)) (setq cat-list-no-dates (cons cat cat-list-no-dates))) (setq cat-list (cdr cat-list)))) (mapconcat (function (lambda (x) (when x (replace-regexp-in-string "\\(\\[\\[\\|\\]\\]\\)" "" x)))) cat-list-no-dates ", ")) (planner-task-plan task))) (task-due (when task-date (concat "\nDUE:" (icalendar--date-to-isodate task-date)))) (contents (concat task-due "\nSUMMARY:" (planner-task-description task) "\nCATEGORIES:" task-categories))) (setq result (concat result header contents "\nEND:VTODO")))) (setq tasks (cdr tasks))) (let ((coding-system-for-write 'utf-8)) (insert "BEGIN:VCALENDAR") (insert "\nPRODID:-//Emacs//NONSGML planner-ical.el//EN") (insert "\nVERSION:2.0") (when result (insert result)) (insert "\nEND:VCALENDAR\n")))) (defun planner-ical-export-this-page () "Display the tasks on the current page in iCal format." (interactive) (if (planner-derived-mode-p 'planner-mode) (planner-ical-export-page (planner-page-name)) (error "Not in planner page"))) (provide 'planner-ical) ;;; planner-ical.el ends here planner-el/planner-id.el000066400000000000000000000307631226462314700155060ustar00rootroot00000000000000;;; planner-id.el --- planner.el extension for global task IDs ;; Copyright (C) 2003, 2004, 2005, 2008 Free Software Foundation, Inc. ;; Author: Sacha Chua ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; After loading planner.el, place planner-id.el in your load path ;; and add this to your .emacs ;; ;; (require 'planner-id) ;; ;; This module modifies the behavior of planner.el, adding global task ;; IDs so that tasks can be edited and updated. ;; ;; To automatically update linked tasks whenever you save a planner ;; file, set planner-id-update-automatically to a non-nil value. This ;; does not update completed or cancelled tasks. See documentation for ;; planner-id-update-tasks-on-page to find out how to force updates. ;; ;; Planner IDs are of the form {{Identifier:Number}} ;; ;; Alternatives: If you don't mind using a function to change your ;; task descriptions, you may find M-x planner-edit-task-description ;; easier to use. Other changes (A/B/C, status) can be applied with ;; M-x planner-update-task after you edit the buffer. ;;; Contributors: ;; Oliver Krause : Main idea, testing. ;; Jim Ottaway provided a fix for interaction of task IDs with ;; multiple links, as well as a regexp bug. ;; Yann Hodique helped port this to Muse. (require 'planner) ;;; Code: (defgroup planner-id nil "Planner ID options." :prefix "planner-id-" :group 'planner) (defcustom planner-id-add-task-id-flag t "Non-nil means add task IDs to newly-created tasks." :type 'boolean :group 'planner-id) (defcustom planner-id-tracking-file "~/.planner-id" "File that stores an alist with the current planner ids." :type 'file :group 'planner-id) (defcustom planner-id-update-automatically t "Non-nil means update linked files automatically when file is saved." :type 'boolean :group 'planner-id) (defface planner-id-face '((((class color) (background light)) (:foreground "lightgray")) (t (:foreground "darkgray"))) "Face for planner ID links." :group 'planner-id) (defvar planner-id-values nil "Alist with (key nextvalue) pairs.") (defvar planner-id-regexp "{{\\([^:\n]+\\):\\([0-9]+\\)}}" "Regexp matching planner IDs.") (defun planner-id-get-id-from-string (string &optional key) "Return the planner ID in STRING as (identifier number). If KEY is specified, match against that." (when (string-match (concat "{{\\(" (or key "[^:\n]+") "\\):\\([0-9]+\\)}}") string) (cons (planner-match-string-no-properties 1 string) (planner-match-string-no-properties 2 string)))) (defun planner-id-get-current-id () "Return the planner ID on the current line as (identifier number)." (planner-id-get-id-from-string (buffer-substring (planner-line-beginning-position) (planner-line-end-position)))) (defun planner-id-format-as-string (id) "Return the planner ID as a string of the form {{identifier:number}}." (concat "{{" (car id) ":" (cdr id) "}}")) ;;;###autoload (defun planner-id-find-task (task-info &optional point) "Find task described by TASK-INFO. If POINT is non-nil, start from there. If task is found, move point to line beginning and return non-nil. If task is not found, leave point at POINT or the start of the buffer and return nil." (goto-char (or point (point-min))) (let ((task-id (cond ;; Task ID ((listp task-info) (planner-id-get-id-from-string (planner-task-description task-info))) ;; Just the ID ((numberp task-info) (cons "Tasks" (number-to-string task-info))) ;; ID as string ((stringp task-info) (cons "Tasks" task-info)))) (found nil)) (when (re-search-forward (concat planner-task-regexp ".*" (regexp-quote (if task-id (planner-id-format-as-string task-id) (planner-task-description task-info)))) nil t) (goto-char (planner-line-beginning-position))))) ;;; Redeclaration ;;;###autoload (defun planner-id-jump-to-linked-task (&optional info) "Display the linked task page. If INFO is specified, follow that task instead." (interactive) (let* ((task-info (or info (planner-current-task-info))) (link (and task-info (planner-task-link task-info)))) (when (planner-local-page-p link) (planner-find-file link) (widen) (planner-id-find-task task-info)))) (defun planner-id-save () "Save `planner-id-values' in `planner-id-tracking-file'." (with-temp-file planner-id-tracking-file (print planner-id-values (current-buffer)))) (defun planner-id-make-global-id (identifier) "Return a globally unique ID as (IDENTIFIER number)." (planner-id-load) (let ((result (cons identifier (number-to-string (let ((elem (assoc identifier planner-id-values))) (if elem (setcdr elem (1+ (cdr elem))) (add-to-list 'planner-id-values (cons identifier 0)) 0)))))) (planner-id-save) result)) (defun planner-id-load () "Read the data from `planner-id-tracking-file'." (setq planner-id-values nil) (with-temp-buffer (condition-case nil (progn (insert-file-contents-literally planner-id-tracking-file) (goto-char (point-min)) (setq planner-id-values (read (current-buffer)))) (error (message "Could not read planner-id-values from %s. Setting it to nil." planner-id-tracking-file))))) ;;;###autoload (defun planner-id-add-task-id-maybe () "Add task ID if `planner-id-add-task-id-flag' is non-nil." (when planner-id-add-task-id-flag (planner-id-add-task-id))) (defun planner-id-add-task-id () "Add a task ID for the current task if it does not have one yet. Update the linked task page, if any." (interactive) (save-window-excursion (save-excursion (let* ((task-info (planner-current-task-info))) (unless (or (not task-info) (planner-id-get-current-id)) (planner-edit-task-description (concat (planner-task-description task-info) " " (planner-id-format-as-string (planner-id-make-global-id "Tasks"))))))))) (defun planner-id-update-tasks-on-page (&optional force) "Update all tasks on this page. Completed or cancelled tasks are not updated. This can be added to `write-file-functions' (CVS Emacs) or `write-file-hooks'. If FORCE is non-nil, completed and cancelled tasks are also updated." (interactive (list current-prefix-arg)) ;; Prevent planner-id updates from cascading (let ((planner-id-update-automatically nil)) (with-planner-update-setup (goto-char (point-min)) (while (re-search-forward (concat (if force planner-task-regexp planner-live-task-regexp) ".*?{{Tasks:[0-9]+}}") nil t) (planner-update-task) ;; Force the next line to be considered even if ;; planner-multi-update-task kicked in. (forward-line 1)))) nil) (defun planner-id-remove-tasks-on-page () "Remove the task IDs from all tasks on this page. This function does _not_ update tasks on linked pages." (save-excursion (goto-char (point-min)) (while (re-search-forward (concat planner-task-regexp "\\(.*?\\)\\(\\s-+{{Tasks:[0-9]+}}\\)") nil t) (replace-match "" t t nil 1)))) (defun planner-id-add-task-id-to-all () "Add a task ID for all the tasks on the page. Update the linked page, if any." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward planner-task-regexp nil t) (planner-id-add-task-id)) (font-lock-fontify-buffer))) (defun planner-id-at-point (&optional pos) "Return non-nil if a URL or Wiki link name is at POS." (if (or (null pos) (and (char-after pos) (not (eq (char-syntax (char-after pos)) ? )))) (let ((case-fold-search nil) (here (or pos (point)))) (save-excursion (goto-char here) (skip-chars-backward " \t\n") (or (looking-at "{{Tasks:[^}\n]+}}") (and (search-backward "{{" (planner-line-beginning-position) t) (looking-at "{{Tasks:[^}\n]+}}")) (<= here (match-end 0))))))) (eval-and-compile (require 'compile) (unless (boundp 'grep-command) ;; Emacs 21 CVS (require 'grep))) (defun planner-id-search-id (id) "Search for all occurrences of ID." (interactive "MID: ") (grep (concat (or grep-command "grep") " " (shell-quote-argument id) " " (shell-quote-argument (expand-file-name (planner-directory))) "/*"))) (defun planner-id-follow-id-at-point () "Display a list of all pages containing the ID at point." (interactive current-prefix-arg) (if (planner-id-at-point) (planner-id-search-id (match-string 0)) (error "There is no valid link at point"))) ;; Very ugly compatibility hack. (defmacro planner-follow-event (event) (if (featurep 'xemacs) `(progn (set-buffer (window-buffer (event-window event))) (and (event-point event) (goto-char (event-point event)))) `(progn (set-buffer (window-buffer (posn-window (event-start event)))) (goto-char (posn-point (event-start event)))))) (defun planner-id-follow-id-at-mouse (event) "Display a list of all pages containing the ID at mouse. EVENT is the mouse event." (interactive "eN") (save-excursion (planner-follow-event event)) (when (planner-id-at-point) (planner-id-search-id (match-string 0)))) ;; (defvar planner-id-keymap ;; (let ((map (make-sparse-keymap))) ;; (define-key map [return] 'planner-id-follow-id-at-point) ;; (define-key map [(control ?m)] 'planner-id-follow-id-at-point) ;; (define-key map [(shift return)] 'planner-id-follow-id-at-point) ;; (if (featurep 'xemacs) ;; (progn ;; (define-key map [(button2)] 'planner-id-follow-id-at-mouse) ;; (define-key map [(shift button2)] 'planner-id-follow-id-at-mouse)) ;; (define-key map [(mouse-2)] 'planner-id-follow-id-at-mouse) ;; (define-key map [(shift mouse-2)] 'planner-id-follow-id-at-mouse)) ;; (unless (eq emacs-major-version 21) ;; (set-keymap-parent map planner-mode-map)) ;; map) ;; "Local keymap used by planner when on an ID.") ;;;###autoload (defun planner-id-markup (beg end &optional verbose) "Highlight IDs as unobtrusive, clickable text from BEG to END. VERBOSE is ignored." (goto-char beg) (while (re-search-forward "{{[^}\n]+}}" end t) (planner-highlight-region (match-beginning 0) (match-end 0) 'planner-id 60 (list 'face 'planner-id-face 'intangible nil ;;'keymap planner-id-keymap )))) ;;;###autoload (defun planner-id-update-tasks-maybe () "Update tasks depending on the value of `planner-id-update-automatically'." (when planner-id-update-automatically (planner-id-update-tasks-on-page))) ;;;###autoload (defun planner-id-setup () "Hook into `planner-mode'." (add-hook 'muse-colors-buffer-hook 'planner-id-markup t t) (add-hook (if (and (boundp 'write-file-functions) (not (featurep 'xemacs))) 'write-file-functions 'write-file-hooks) 'planner-id-update-tasks-maybe nil t)) (add-hook 'planner-mode-hook 'planner-id-setup) (add-hook 'planner-create-task-hook 'planner-id-add-task-id-maybe) (setq planner-jump-to-linked-task-function 'planner-id-jump-to-linked-task) (setq planner-find-task-function 'planner-id-find-task) (eval-after-load "planner-publish" '(add-to-list 'planner-publish-markup-regexps '(1270 planner-id-regexp 0 ""))) (provide 'planner-id) ;;; planner-id.el ends here planner-el/planner-ledger.el000066400000000000000000000172731226462314700163550ustar00rootroot00000000000000;;; planner-ledger.el --- ledger support for planner ;; Copyright (C) 2004, 2008 Will Glozer (will AT glozer DOT net) ;; Parts copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. ;; Author: Will Glozer (will AT glozer DOT net) ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This planner module provides integration between planner and ;; John Wiegley's ledger accounting program available at: ;; ;; http://newartisans.com/johnw/ledger.tar.gz ;; ;; planner-ledger can insert a ledger balance overview and a list of pending ;; transactions into a planner day page. To do so, simply add a hook: ;; ;; (add-hook 'planner-goto-hook 'planner-ledger-insert-maybe) ;; ;; and make sure `planner-day-page-template' includes sections that match ;; `planner-ledger-balance-regexp' and `planner-ledger-pending-regexp'. ;; ;; planner-ledger can also create a new ledger entry based on a planner ;; task that matches `planner-ledger-payment-task-regexp', which by default ;; matches entries like: ;; ;; #B0 _ payment due: Payee, $100.00 from 2004.07.01 ;; ;; Bind `planner-ledger-add-entry-from-task' to a convenient key stroke and ;; execute it when in a payment task. ;;; Contributors ;; Travis B. Hartwell made this usable with new versions of ledger and ;; made it more flexible. (require 'ledger) (require 'planner) ;;; Code: (defgroup planner-ledger nil "Planner-ledger provides integration between Planner and John Wiegley's ledger accounting program." :group 'planner) (defcustom planner-ledger-data-file nil "Ledger file to use. This is the full path to the data file." :type '(file :must-match t) :group 'planner-ledger) (defcustom planner-ledger-balance-regexp "^\* Ledger *$" "Section marker for insertion of ledger balance." :type 'regexp :group 'planner-ledger) (defcustom planner-ledger-pending-regexp "^\*\* Pending Transactions *$" "Section marker for insertion of pending ledger transactions." :type 'regexp :group 'planner-ledger) (defcustom planner-ledger-balance-accounts '("Assets" "Liabilities" "-Equity") "Accounts to include or exclude from ledger balance overview." :type '(repeat string) :group 'planner-ledger) (defcustom planner-ledger-balance-args '("-s" "-e" "next month" "balance") "Command line arguments for ledger balance." :type '(repeat string) :group 'planner-ledger) (defcustom planner-ledger-register-args '("-U" "register") "Command line arguments for ledger register." :type '(repeat string) :group 'planner-ledger) (defcustom planner-ledger-payment-task-regexp (concat planner-task-regexp "payment\\s-+due:\\s-+\\([^,]+?\\),\\s-*\\([[:graph:]]+\\)") "Regular expression matching planner tasks for ledger payment. The first parenthesized group should match the payee. The second group should match the amount. Example task: #A0 _ payment due: foobar, $1000.00 some comment here" :type 'regexp :group 'planner-ledger) ;;;###autoload (defun planner-ledger-insert-maybe () "Maybe insert ledger sections into a Planner page." (interactive) (planner-ledger-insert-balance-maybe) (planner-ledger-insert-pending-maybe)) (defun planner-ledger-insert-balance-maybe () "Maybe insert ledger account balances a Planner page. The accounts are specified in planner-ledger-balance-accounts." (interactive) (planner-ledger-clear-section-balance) (apply 'planner-ledger-insert-section-maybe planner-ledger-balance-regexp (append planner-ledger-balance-args planner-ledger-balance-accounts))) (defun planner-ledger-insert-pending-maybe () "Maybe insert ledger pending transaction into a Planner page." (interactive) (planner-ledger-clear-section-pending) (apply 'planner-ledger-insert-section-maybe planner-ledger-pending-regexp (append planner-ledger-register-args))) (defun planner-ledger-insert-section-maybe (regexp &rest ledger-args) "Maybe insert a ledger section into a Planner page. Argument REGEXP is the section heading to find. Optional argument LEDGER-ARGS contains the arguments to pass to `ledger-run-ledger'." (save-excursion (goto-char (point-min)) (when (re-search-forward regexp nil t) (progn (newline 2) (apply 'planner-ledger-run-ledger ledger-args))))) (defun planner-ledger-clear-section-balance () "Clear the planner-ledger section for Ledger balance." (interactive) (save-excursion (planner-ledger-clear-section planner-ledger-balance-regexp "^\\*"))) (defun planner-ledger-clear-section-pending () "Clear the planner-ledger section for pending transactions." (interactive) (save-excursion (planner-ledger-clear-section planner-ledger-pending-regexp "^\\*"))) (defun planner-ledger-clear-section (regexp-start regexp-end) "Clear a planner ledger section." (goto-char (point-min)) (when (re-search-forward regexp-start nil t) (progn (forward-line) (delete-region (point) (if (re-search-forward regexp-end nil t) (line-beginning-position) (point-max)))))) (defun planner-ledger-goto-section-end (regexp-start) "Goto the end of the current section or end of buffer. Assumes that sections are marked with an asterisk." (if (re-search-forward regexp-start nil t) (line-beginning-position) (point-max))) (defun planner-ledger-add-entry-from-task () "Add a new ledger entry from the task at point." (interactive) (save-excursion (beginning-of-line) (if (re-search-forward planner-ledger-payment-task-regexp (planner-line-end-position) t) (let* ((payee (match-string 1)) (amount (match-string 2)) (date (planner-filename-to-calendar-date (buffer-name))) (buffer (find-buffer-visiting planner-ledger-data-file))) (unless buffer (setq buffer (find-file planner-ledger-data-file))) (pop-to-buffer buffer) (ledger-add-entry (format "%d/%02d/%02d %s %s" (extract-calendar-year date) (extract-calendar-month date) (extract-calendar-day date) payee amount))) (message "Not in a ledger payment task")))) (defun planner-ledger-run-ledger (&rest ledger-args) "Run ledger for planner-ledger. Run the ledger binary with ledger-run-ledger using the value of `planner-ledger-data-file'. If the file is open in a buffer, use the buffer. Otherwise specify the file as an option to the ledger binary command and avoid loading it in Emacs." (let ((buffer (get-file-buffer planner-ledger-data-file))) (if buffer (apply 'ledger-run-ledger buffer ledger-args) (apply #'call-process (append (list ledger-binary-path nil t nil "-f" planner-ledger-data-file) ledger-args))))) (provide 'planner-ledger) ;;; planner-ledger.el ends here planner-el/planner-lisp.el000066400000000000000000000042221226462314700160500ustar00rootroot00000000000000;;; planner-lisp.el --- Interactive Emacs Lisp integration for Planner mode ;; Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. ;; Author: Sacha Chua ;; Keywords: planner, gnus ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file allows you to launch Emacs Lisp functions ;; from a planner page. ;; ;; Example: ;; [[lisp:/plan][Plan]] will be rendered as "Plan". Selecting the link ;; will run the plan function interactively. ;; ;; If the link is a lisp form it is evaluated non-interactively: ;; [[lisp:/(man "bash")][bash manual]] will be rendered as "bash ;; manual". Selecting the link will show the bash man page in Emacs. ;;; Contributors: ;; Gerd Flaig fixed the docstring for `planner-lisp-browse-url'. ;; Jim Ottaway made it such that if the URL like a lisp form, read and ;; evaluate it, otherwise call it interactively as before. ;;; Code: (require 'planner) ;;;###autoload (defun planner-lisp-browse-url (url) "If this is a LISP URL, evaluate it." (when (string-match "\\`lisp:/*\\(.+\\)" url) (let ((form (match-string 1 url))) (if (string-match "\\`\\s-*\\((.+)\\)\\s-*\\'" form) (eval (read (match-string 1 form))) (eval (read (concat "(call-interactively '" form ")"))))) t)) (planner-add-protocol "lisp:/*" 'planner-lisp-browse-url nil) (provide 'planner-lisp) ;;; planner-lisp.el ends here planner-el/planner-log-edit.el000066400000000000000000000111331226462314700166040ustar00rootroot00000000000000;;; planner-log-edit.el --- Record VC commits as a note in todays planner file ;; Copyright (C) 2004, 2008 Simon Winwood (sjw AT cse.unsw.edu.au) ;; Parts copyright (C) 2004, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2004, 2008 Dryice Dong Liu (dryice AT liu.com.cn) ;; Parts copyright (C) 2005, 2008 Yann Hodique (yann.hodique AT gmail.com) ;; Author: Simon Winwood ;; Version: 0.1 ;; Keywords: planner, vc, pcl-cvs, log-edit ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file records cvs (and VC) commits into todays planner file. ;;; Contributors: ;; Dryice Dong Liu (dryice AT liu.com.cn) provided the ;; `planner-log-edit-quote-filenames-flag' option and patched the code ;; to use it. ;; Yann Hodique added the possibility to ignore patterns before ;; inserting commit messages as notes (useful for psvn) via the new ;; `planner-log-edit-flush-regexp-list' option. ;;; Code: (require 'planner) (require 'log-edit) (defgroup planner-log-edit nil "Planner options for log-edit." :prefix "planner-log-edit-" :group 'planner) (defcustom planner-log-edit-include-files-flag t "Non-nil means include a list of committed files in the note." :type 'boolean :group 'planner-log-edit) (defcustom planner-log-edit-quote-filenames-flag nil "Non-nil means quote the file names with \"=\"." :type 'boolean :group 'planner-log-edit) (defcustom planner-log-edit-notice-commit-function t "Function that should return non-nil if this commit should be noted. The function will be run in the log buffer." :type '(choice (const :tag "Always note commits" t) function) :group 'planner-log-edit) (defcustom planner-log-edit-flush-regexp-list nil "List of regexps to flush before inserting note" :type '(repeat regexp) :group 'planner-log-edit) (defcustom planner-log-edit-module-name-function 'planner-log-edit-cvs-module "Function that should return a name for the current module." :type 'function :group 'planner-log-edit) (defun planner-log-edit-quote-file-maybe (arg) "Quote ARG if `planner-log-edit-quote-filenames-flag is non-nil." (if planner-log-edit-quote-filenames-flag (concat "=" arg "=") arg)) (defun planner-log-edit-cvs-module () (condition-case nil (when (fboundp 'cvs-get-module) (cvs-get-module)))) ;;;###autoload (defun planner-log-edit-add-note () "Add a note describing the commit to the current planner page." (let* ((buffer (current-buffer)) (files (log-edit-files)) ;; This should be a function call into log-edit, but until it ;; exists ... (module-name (funcall planner-log-edit-module-name-function))) (if (if (functionp planner-log-edit-notice-commit-function) (funcall planner-log-edit-notice-commit-function) planner-log-edit-notice-commit-function) (save-excursion (save-window-excursion (planner-create-note nil) (insert "Commit" (if module-name (concat " in " (planner-log-edit-quote-file-maybe module-name)) "")) (newline) (when planner-log-edit-include-files-flag (insert "Files: ") (insert (mapconcat 'planner-log-edit-quote-file-maybe files " ")) (newline) (newline)) (insert (with-temp-buffer (insert-buffer-substring buffer) (goto-char (point-min)) (mapc (lambda (regexp) (flush-lines regexp)) planner-log-edit-flush-regexp-list) (buffer-string))) ;(insert-buffer-substring buffer) ))))) (add-hook 'log-edit-done-hook 'planner-log-edit-add-note) (provide 'planner-log-edit) ;;; planner-log-edit.el ends here planner-el/planner-mhe.el000066400000000000000000000142501226462314700156540ustar00rootroot00000000000000;;; planner-mhe.el --- MH-E integration for the Emacs Planner ;; Copyright (C) 2004, 2005, 2006, 2008 Christophe Garion ;; Parts copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc. ;; Author: Christophe Garion ;; Author: Sandra Jean Chua ;; Created: <2004-08-09 17:16:57 tof planner-mhe.el> ;; Time-stamp: <2006-09-28 15:05:05 tof planner-mhe.el> ;; Keywords: planner, mh-e ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Inspired by planner-gnus (thanks to Sacha Chua) ;; This file adds annotations for MH-E messages. You will then be able ;; to use M-x planner-create-task-from-buffer to create tasks from ;; MH-E folder or show buffers with the correct annotation. If you ;; create an annotation from a mh-index folder, the message "real" ;; folder will be taken into account. ;;; Contributors: ;; Yann Hodique helped port this to Muse. ;;; Code: (require 'planner) (require 'mh-e) (defun planner-mhe-get-message-folder-from-index () "Returns the name of the message folder in a index folder buffer." (save-excursion (mh-index-previous-folder) (buffer-substring (planner-line-beginning-position) (planner-line-end-position)))) (defun planner-mhe-get-message-real-folder () "Return the name of the current message real folder, so if you use sequences, it will now work." (save-excursion (let* ((folder (if (equal major-mode 'mh-folder-mode) mh-current-folder ;; Refer to the show buffer mh-show-folder-buffer)) (end-index (min (length mh-index-folder) (length folder)))) ;; a simple test on mh-index-data does not work, because ;; mh-index-data is always nil in a show buffer. (if (string= mh-index-folder (substring folder 0 end-index)) (if (equal major-mode 'mh-show-mode) (save-window-excursion (when (buffer-live-p (get-buffer folder)) (progn (pop-to-buffer folder) (planner-mhe-get-message-folder-from-index)))) (planner-mhe-get-message-folder-from-index)) folder)))) (defun planner-mhe-get-message-folder () "Return the name of the current message folder." (if (equal major-mode 'mh-folder-mode) mh-current-folder ;; Refer to the show buffer mh-show-folder-buffer)) (defun planner-mhe-get-message-field (field) "Return a particular field of the current message." (save-excursion (let ((num (if (equal major-mode 'mh-folder-mode) (mh-get-msg-num nil) ;; Refer to the show buffer (mh-show-buffer-message-number))) (folder (planner-mhe-get-message-folder))) (car (split-string (with-temp-buffer (call-process (expand-file-name "anno" mh-progs) nil t nil folder "-list" "-component" field (number-to-string num)) (buffer-string)) "\n"))))) ;;;###autoload (defun planner-mhe-annotation () "If called from a MH-E folder or message buffer, return an annotation. Suitable for use in `planner-annotation-functions'." (when (or (equal major-mode 'mh-folder-mode) (equal major-mode 'mh-show-mode)) (let ((from-header (planner-mhe-get-message-field "From")) (to-header (planner-mhe-get-message-field "To"))) (planner-make-link (concat "mhe://" (planner-mhe-get-message-real-folder) "/" (planner-mhe-get-message-field "Message-Id")) (concat "E-Mail " (if (and planner-ignored-from-addresses from-header (string-match planner-ignored-from-addresses from-header)) ;; Mail from me, so use the To: instead (concat "to " (planner-get-name-from-address to-header)) ;; Mail to me, so use the From: (concat "from " (planner-get-name-from-address from-header)))))))) ;;;###autoload (defun planner-mhe-browse-url (url) "If this is a MH-E URL, jump to it." (when (string-match "\\`mhe://\\(.+\\)/\\([^>\n]+\\)" url) (let* ((folder (match-string 1 url)) (num (match-string 2 url)) (show-buf (concat "show-" folder))) (save-window-excursion (mh-visit-folder folder) (get-buffer-create show-buf) (mh-display-msg (string-to-number (if (= (aref num 0) ?<) ; message-id (car (split-string (with-temp-buffer (call-process (expand-file-name "pick" mh-progs) nil t nil folder "--message-id" num) (buffer-string)) "\n")) num)) folder)) (pop-to-buffer show-buf)))) ;(fset 'planner-get-from 'planner-gnus-get-address) ;(fset 'planner-get-message-id 'planner-gnus-get-message-id) (custom-add-option 'planner-annotation-functions 'planner-mhe-annotation) (add-hook 'planner-annotation-functions 'planner-mhe-annotation) (planner-add-protocol "mhe://" 'planner-mhe-browse-url nil) ; to set the mh-path etc. variables (mh-find-path) (provide 'planner-mhe) ;;; planner-mhe.el ends here planner-el/planner-multi.el000066400000000000000000001115401226462314700162350ustar00rootroot00000000000000;;; planner-multi.el --- Multiple page support for planner.el ;; Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. ;; Author: Sandra Jean Chua (Sacha) ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;; TODO: completion that makes sense! ;;; Commentary: ;; After (require 'planner-multi), you should be able to create tasks ;; on multiple pages using M-x planner-create-task-from-buffer or M-x ;; planner-create-task. Notes should also work if you have at least ;; remember--dev--1.0--patch-21. ;;; Contributors: ;; Jim Ottaway made this work better with planner-appt.el and fixed ;; several bugs. ;; Yann Hodique helped in porting this to use Muse rather than ;; emacs-wiki. ;; Sergey Vlasov provided a bugfix for lists with dates in them. ;; Marco Gidde provided a patch that fixes a problem with extraneous ;; brackets. ;; Seth Falcon contributed a small improvement to ;; `planner-multi-replan-task'. (require 'planner) (condition-case err (require 'crm) ('file-error (message "Could not load crm; cumbersome completing read used"))) ;;; Code: (defcustom planner-multi-separator " " "String that separates multiple page references. For best results, this should be something recognized by `muse-link-at-point' so that links are highlighted separately." :type 'string :group 'planner) (defcustom planner-multi-copy-tasks-to-page nil "If non-nil, planner page to automatically copy tasks to. Example: TaskPool. You can specify multiple pages by separating them with `planner-multi-separator', such as \"[[AllTasksByProject][p]] [[AllTasksByContext][c]]\"." :type 'string :group 'planner-multi) (defcustom planner-multi-date-links-last-p t "If non-nil, put day-page links after other pages on the task line. Otherwise, put them before other pages on the task line." :type 'boolean :group 'planner-multi) ;;;_+ Utility functions (defun planner-multi-next-link (current link-list) "Return the item following CURRENT in LINK-LIST." (setq current (or current (planner-page-name))) (let ((found nil) (search link-list)) (while (and (car search) (null found)) (when (string= (planner-link-base (car search)) current) (setq found (car (cdr search)))) (setq search (cdr search))) (or found (car link-list)))) (defun planner-multi-make-link (list) "Create a text link for LIST." (mapconcat 'planner-make-link list planner-multi-separator)) (defun planner-multi-link-member (page links) "Return non-nil if PAGE is a member of LINKS." (let (found) (while (and (car links) (null found)) (when (string= (planner-link-base (car links)) page) (setq found (car links))) (setq links (cdr links))) found)) (defun planner-multi-link-delete (page links) "Delete PAGE from LINKS." (let (results) (while links (unless (string= (planner-link-base (car links)) page) (setq results (cons (car links) results))) (setq links (cdr links))) (nreverse results))) (defun planner-multi-split (string) "Return a list of links in STRING." ;; "[[foo bar]] baz [[qux quux]]" should return ("[[foo bar]]" "baz" "[[qux quux]]"), so a simple split-string won't do (if (stringp string) (let (list (pos 0) (len (length string))) (while (< pos len) (if (string-match (concat (if (= (aref string pos) ?\[) "\\(\\[\\[.+?\\]\\]\\)" "\\(.*?\\)") (regexp-quote planner-multi-separator) "+") string pos) (progn (add-to-list 'list (match-string 1 string) t) (setq pos (match-end 0))) (add-to-list 'list (substring string pos) t) (setq pos len))) list) string)) ;;;_+ Tasks (defadvice planner-task-info-from-string (after planner-multi activate) "Store split task strings in position 5 (`planner-task-link')." (when ad-return-value (let ((sub-list (cdr (cdr (cdr (cdr (cdr ad-return-value)))))) links) (when (car (cdr sub-list)) (setq links (planner-multi-split (car (cdr sub-list))))) (unless (planner-multi-link-member (planner-page-name) links) (add-to-list 'links (planner-page-name))) (setcar sub-list links)))) (defadvice planner-task-link (around planner-multi activate) "Return the next link of a task for compatibility with old code." (setq ad-return-value (if (listp (nth 5 info)) (let ((link (planner-multi-next-link (planner-page-name) (nth 5 info)))) (when link (planner-link-base link))) (nth 5 info)))) (defadvice planner-task-plan (around planner-multi activate) "Return the first plan of a task for compatibility with old code." (if (and (nth 5 info) (listp (nth 5 info))) (let ((current (nth 5 info))) (while current (unless (string-match planner-date-regexp (planner-link-base (car current))) (setq ad-return-value (planner-link-base (car current))) (setq current nil)) (setq current (cdr current)))) ad-do-it)) (defun planner-multi-task-date (info) "Return the date assigned to a task given INFO." (or (let ((date (nth 8 info))) (and (stringp date) (string-match planner-date-regexp date) date)) (let ((links (nth 5 info)) found-date) (when (listp links) (while links (let ((page (planner-link-base (car links)))) (if (string-match planner-date-regexp page) (setq found-date page links nil) (setq links (cdr links))))) found-date)))) (defalias 'planner-task-date 'planner-multi-task-date) (defun planner-multi-task-link-as-list (info) "Return the page links of INFO as a list." (if (listp (nth 5 info)) (nth 5 info) (list (nth 5 info)))) (defalias 'planner-task-link-as-list 'planner-multi-task-link-as-list) (defun planner-multi-task-xref (page) "Copy the current task to PAGE." (interactive (list (planner-make-link (planner-read-name (planner-file-alist))))) (let* ((info (planner-current-task-info)) (links (planner-multi-task-link-as-list info))) (unless (listp page) (setq page (planner-multi-split page))) (while page (unless (planner-multi-link-member (car page) links) (add-to-list 'links (car page) t)) (setq page (cdr page))) (planner-replan-task (planner-multi-link-delete (planner-task-date info) links)))) (defun planner-multi-copy-or-move-task (&optional date force) "Move the current task to DATE. If this is the original task, it copies it instead of moving. Most of the time, the original should be kept in a planning file, but this is not required. If FORCE is non-nil, the task is moved regardless of status. It also works for creating tasks from a Note. Use `planner-replan-task' if you want to change the plan page in order to get better completion. This function is the most complex aspect of planner.el." (interactive (list (let ((planner-expand-name-favor-future-p (or planner-expand-name-favor-future-p planner-task-dates-favor-future-p))) (planner-read-date)) current-prefix-arg)) (let ((info (planner-current-task-info)) (case-fold-search nil)) (if (or (null date) (string-match planner-date-regexp date)) (if (and (planner-task-link-text info) (or (listp (planner-task-link-text info)) (string-match (concat "^\\(" muse-explicit-link-regexp "\\|[1-9][0-9][0-9][0-9]\\.[0-9]+\\.[0-9]+" "\\)" "\\(" (regexp-quote planner-multi-separator) "\\(" muse-explicit-link-regexp "\\|[1-9][0-9][0-9][0-9]\\.[0-9]+\\.[0-9]+" "\\)\\)+$") (planner-task-link-text info)))) (progn (when (equal date (planner-page-name)) (error "Cannot move a task back to the same day")) (unless force (when (equal (planner-task-date info) date) (error "Cannot move a task back to the same day")) (when (equal (planner-task-status info) "X") (error "Cannot reschedule a completed task")) (when (equal (planner-task-status info) "C") (error "Cannot reschedule a cancelled task"))) ;; Multiple pages (with-planner-update-setup ;; Delete from date page (let ((old-date (planner-task-date info)) (links (planner-multi-split (planner-task-link-text info)))) (when old-date (planner-find-file (planner-link-base old-date)) (planner-find-task info) (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position))))) ;; Update (setq links (planner-multi-link-delete (planner-task-date info) links)) (planner-find-file (planner-link-base (car links))) (when date (setq links (cons date links))) (if (planner-find-task info) (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position)))) (planner-seek-task-creation-point)) (insert (planner-format-task info nil nil nil nil (planner-multi-make-link links)) "\n") (forward-char -1) ;; Update all linked tasks (planner-update-task)))) (planner-copy-or-move-task-basic date force)) (when (planner-replan-task date) t)))) (defalias 'planner-copy-or-move-task 'planner-multi-copy-or-move-task) (defun planner-multi-task-string (info page-name links &optional new-pages) "Return task line for INFO on PAGE-NAME with LINKS, a list of pages to link to. If non-nil, PAGES should be a list of the `planner-link-base's of LINKS." ;; Set up the new links list for easy testing (setq new-pages (mapcar 'planner-link-base links)) (cond ;; If this is a no-link task ((and (= (length new-pages) 1) (string= (car new-pages) page-name)) (planner-format-task info nil nil nil nil "" "")) ;; If this is a standard singly-linked task (date, plan) ((and (= (length new-pages) 2) (string-match planner-date-regexp (car new-pages)) (not (string-match planner-date-regexp (cadr new-pages)))) (planner-format-task info nil nil nil nil (planner-make-link (if (string-match planner-date-regexp page-name) (cadr new-pages) (car new-pages))))) ;; If this is a standard singly-linked task (plan, date) ((and (= (length new-pages) 2) (not (string-match planner-date-regexp (car new-pages))) (string-match planner-date-regexp (cadr new-pages))) (planner-format-task info nil nil nil nil (planner-make-link (if (string-match planner-date-regexp page-name) (car new-pages) (cadr new-pages))))) ;; Multilink (t (planner-format-task info nil nil nil nil (planner-make-link new-pages))))) (defun planner-multi-replan-task (pages) "Change or assign the plan page for the current task. PAGES is the new plan page for the task. Use `planner-copy-or-move-task' if you want to change the date. With a prefix, provide the current link text for editing." (interactive (list (planner-read-name (planner-file-alist) nil ;; The list of planner pages associated with this task (when current-prefix-arg (planner-multi-make-link (planner-multi-filter-links planner-date-regexp (planner-multi-task-link-as-list (planner-current-task-info)) t)))))) (when (stringp pages) (setq pages (planner-multi-split pages))) (let* ((info (planner-current-task-info)) (old-pages ;; Pages the task is currently assigned to (planner-multi-task-link-as-list info)) new-pages date) ; Pages from page-name ;; Add dates back to the list of pages (setq date (planner-task-date info)) (when date (add-to-list 'pages date planner-multi-date-links-last-p)) (unless pages (error "Cannot replan this task; it will disappear")) (with-planner-update-setup ;; Set up the new links list for easy testing (setq new-pages (mapcar 'planner-link-base pages)) ;; Map over the old pages, removing if not in the new one and ;; updating if it is (while old-pages (planner-find-file (car old-pages)) (cond ((planner-find-task info) (delete-region (planner-line-beginning-position) (1+ (planner-line-end-position)))) ((member (planner-page-name) new-pages) (planner-seek-task-creation-point))) (when (member (planner-page-name) new-pages) (insert (planner-multi-task-string info (planner-page-name) pages new-pages) "\n")) (setq old-pages (cdr old-pages))) ;; Map over any new pages that were not included (setq old-pages (mapcar 'planner-link-base (planner-multi-task-link-as-list info))) (mapcar (lambda (page) (unless (member page old-pages) (planner-find-file page) (if (planner-find-task info) (delete-region (planner-line-beginning-position) (1+ (planner-line-end-position))) (planner-seek-task-creation-point)) (insert (planner-multi-task-string info (planner-page-name) pages new-pages) "\n"))) new-pages)))) (defalias 'planner-replan-task 'planner-multi-replan-task) (defun planner-multi-update-task () "Update the current task's priority and status on the linked page. Tasks are considered the same if they have the same description. This function allows you to force a task to be recreated if it disappeared from the associated page. Note that the text of the task must not change. If you want to be able to update the task description, see planner-id.el." (interactive) (let* ((info (planner-current-task-info)) (links (planner-multi-task-link-as-list info)) (new-pages (mapcar 'planner-link-base links))) ;; Jump around (with-planner-update-setup (while links (planner-find-file (planner-link-base (car links))) (if (planner-find-task info) ;; Already there, so update only if changed (unless (planner-tasks-equal-p info (planner-current-task-info)) (delete-region (planner-line-beginning-position) (planner-line-end-position)) (insert (planner-multi-task-string info (planner-page-name) (planner-multi-task-link-as-list info) new-pages))) ;; Not yet there, so add it (planner-seek-task-creation-point) (insert (planner-multi-task-string info (planner-page-name) (planner-multi-task-link-as-list info) new-pages) "\n")) (setq links (cdr links)))))) (defalias 'planner-update-task 'planner-multi-update-task) (defun planner-multi-tasks-equal-p (task-a task-b) "Return t if TASK-A and TASK-B are equivalent. This is true if they have the same value for priority, status, description, and links." (and (string= (or (planner-task-priority task-a) "") (or (planner-task-priority task-b) "")) (string= (or (planner-task-status task-a) "") (or (planner-task-status task-b) "")) (string= (or (planner-task-description task-a) "") (or (planner-task-description task-b) "")) (if (or (string-match (regexp-quote planner-multi-separator) (or (planner-task-link-text task-a) "")) (string-match (regexp-quote planner-multi-separator) (or (planner-task-link-text task-b) ""))) (string= (planner-task-link-text task-a) (planner-task-link-text task-b)) (and (string= (or (planner-task-plan task-a) "") (or (planner-task-plan task-b) "")) (string= (or (planner-task-date task-a) "") (or (planner-task-date task-b) "")))))) (defalias 'planner-tasks-equal-p 'planner-multi-tasks-equal-p) (defadvice planner-delete-task (around planner-multi activate) "Remove this note from all linked pages." ;; Delete the current note. (save-window-excursion (let ((info (planner-current-task-info)) links) (setq links (planner-multi-task-link-as-list info)) (if (<= (length links) 1) ad-do-it (while links (planner-find-file (planner-link-base (car links))) (when (planner-find-task info) (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position))))) (setq links (cdr links))))))) (defadvice planner-make-link (around planner-multi activate) "Escape separately if using `planner-multi-separator'." (if (ad-get-arg 2) ad-do-it (let ((case-fold-search nil)) (cond ((listp link) (setq ad-return-value (mapconcat 'muse-make-link link planner-multi-separator))) ((string-match (regexp-quote planner-multi-separator) link) (setq ad-return-value (mapconcat 'muse-make-link (planner-multi-split link) planner-multi-separator))) (t ad-do-it))))) (defun planner-multi-filter-links (regexp links-list &optional nonmatch) "Return a list of links matching REGEXP in LINKS-LIST. If NONMATCH is non-nil, return non-matching links instead." (delq nil (mapcar (lambda (item) (when (funcall (if nonmatch 'not 'null) (string-match regexp item)) item)) links-list))) (defun planner-multi-create-task-from-info (info &optional priority number status description link-text date plan) "Create a task in the date and plan pages based on INFO. Optional arguments PRIORITY, NUMBER, STATUS, DESCRIPTION, LINK-TEXT, DATE, and PLAN override those in INFO. Create task on multiple pages if necessary." (setq link-text (or link-text (planner-task-link-text info))) (when planner-multi-copy-tasks-to-page (if (and link-text planner-multi-copy-tasks-to-page) (unless (string-match (regexp-quote (planner-link-base planner-multi-copy-tasks-to-page)) link-text) (setq link-text (concat link-text planner-multi-separator planner-multi-copy-tasks-to-page))) (setq link-text planner-multi-copy-tasks-to-page))) (if (and link-text (string-match (regexp-quote planner-multi-separator) link-text)) (progn ;; Create the task on all pages. (let ((list (planner-multi-split (or link-text (planner-task-link-text info)))) (link-text (or link-text (planner-task-link-text info)))) (when (or date (planner-task-date info)) (setq list (planner-multi-filter-links planner-date-regexp list t)) (add-to-list 'list (or date (planner-task-date info)) planner-multi-date-links-last-p) (setq link-text (planner-multi-make-link list))) (save-window-excursion (while list (planner-find-file (planner-link-base (car list))) (planner-seek-task-creation-point) (insert (planner-format-task info priority number status description link-text) "\n") (setq list (cdr list))) (forward-line -1) (run-hooks 'planner-create-task-hook)))) (planner-create-task-from-info-basic info priority number status description link-text date plan))) (setq planner-create-task-from-info-function 'planner-multi-create-task-from-info) (defun planner-multi-task-delete-this-page () "Remove this task from the current page." (interactive) (let ((info (planner-current-task-info))) (planner-multi-replan-task (planner-multi-link-delete (planner-task-date info) (planner-multi-link-delete (planner-page-name) (planner-multi-task-link-as-list (planner-current-task-info))))))) (defun planner-multi-edit-task-description (description) "Update multiple pages." (interactive (list (let* ((info (planner-current-task-info)) (planner-task-history (list (planner-task-description info)))) (unless info (error "No task on current line")) (read-string "New description: " (cons (planner-task-description info) 1) '(planner-task-history . 1) (planner-task-description info))))) (let ((point (point))) (with-planner-update-setup (let* ((info (planner-current-task-info)) (newinfo (planner-current-task-info)) (links (planner-multi-task-link-as-list info)) (new-pages (mapcar 'planner-link-base links))) (setcar (cdr (cdr (cdr (cdr newinfo)))) description) (while links (planner-find-file (planner-link-base (car links))) (if (planner-find-task info) ;; Already there, so update only if changed (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position)))) ;; Not yet there, so add it (planner-seek-task-creation-point)) (insert (planner-multi-task-string newinfo (planner-page-name) (planner-multi-task-link-as-list info) new-pages) "\n") (setq links (cdr links))))) (goto-char point))) (defalias 'planner-edit-task-description 'planner-multi-edit-task-description) ;; Todo: copy-or-move ;;;_+ Notes (defadvice planner-current-note-info (after planner-multi activate) "Store split note strings in position 4 (`planner-note-link')." (let ((sub-list (cdr (cdr (cdr (cdr ad-return-value)))))) (when (and (car sub-list) (string-match (regexp-quote planner-multi-separator) (car sub-list))) (setcar sub-list (planner-multi-split (car sub-list)))))) (defadvice planner-note-link (around planner-multi activate) "Return the next link of a note for compatibility with old code." (setq ad-return-value (if (and (nth 4 note-info) (listp (nth 4 (ad-get-arg 0)))) (planner-multi-next-link (planner-page-name) (nth 4 (ad-get-arg 0))) (nth 4 note-info)))) (defadvice planner-note-link-text (around planner-multi activate) "Return the link text of a note for compatibility with old code." (setq ad-return-value (if (and (nth 4 note-info) (listp (nth 4 (ad-get-arg 0)))) (planner-make-link (nth 4 note-info)) (nth 4 note-info)))) (defun planner-multi-note-link-as-list (info) "Return the page links of INFO as a list." (if (listp (nth 4 info)) (nth 4 info) (list (nth 4 info)))) (defadvice planner-update-note (around planner-multi activate) "Copy the text from this note to the linked notes, if any." (interactive) (let ((info (planner-current-note-info)) body) (if (= (length (planner-multi-note-link-as-list info)) 1) ad-do-it (save-window-excursion (save-restriction (planner-narrow-to-note) (goto-char (point-min)) (skip-chars-forward ".#0-9") (setq body (buffer-substring-no-properties (point) (point-max)))) (let ((links (planner-multi-note-link-as-list info))) ;; Jump around (while links (planner-visit-link (planner-link-target (car links))) (save-restriction (when (planner-narrow-to-note) (goto-char (point-min)) (skip-chars-forward ".#0-9") (delete-region (point) (point-max)) (insert body))) (setq links (cdr links)))))))) (defun planner-multi-note-xref (page) "Copy the current note to PAGE." (interactive (list (planner-read-name (planner-file-alist)))) (let ((case-fold-search nil)) ;; Modify the current note (save-window-excursion (when (planner-current-note-info) (let (note-num) (save-window-excursion (setq note-num (planner-create-note page))) ;; Add to current (unless (looking-at "^.#[0-9]") (re-search-backward "^.#[0-9]" nil t)) (cond ;; Already a multilink ((re-search-forward (concat "(" "\\(" muse-explicit-link-regexp "\\)" "\\(" (regexp-quote planner-multi-separator) "\\(" muse-explicit-link-regexp "\\)\\)+)") (planner-line-end-position) t) (forward-char -1) (insert planner-multi-separator (planner-make-link (concat page "#" (number-to-string note-num))))) ;; Single link ((re-search-forward (concat "(\\(" muse-explicit-link-regexp "\\))") (planner-line-end-position) t) (forward-char -1) (insert planner-multi-separator (planner-make-link (concat page "#" (number-to-string note-num))) planner-multi-separator (planner-make-link (concat (planner-page-name) "#" (planner-note-anchor (planner-current-note-info)))))) ;; No link yet (t (re-search-forward "\\s-*$" (planner-line-end-position) t) (replace-match (concat " (" (save-match-data (planner-make-link (concat page "#" (number-to-string note-num)))) ")") t t))) (planner-update-note)))))) (defadvice planner-replan-note (around planner-multi activate) "Allow multiple pages." (if (string-match (regexp-quote planner-multi-separator) page) (save-window-excursion (save-restriction (let* ((info (planner-current-note-info)) (links (planner-multi-note-link-as-list info)) (new-links (planner-multi-split page)) (old-anchor (planner-make-link (concat (planner-note-page info) "#" (planner-note-anchor info)))) cursor current-page (old-pages (mapcar 'planner-link-base links))) (when (and (not old-pages) (string-match planner-date-regexp (planner-note-page info))) (setq old-pages (list (planner-note-page info))) (add-to-list 'new-links old-anchor)) ;; Add to new pages (setq cursor new-links) (while cursor (setq current-page (planner-link-base (car cursor))) (when (not (member current-page old-pages)) (setcar cursor (planner-make-link (format "%s#%d" (planner-link-base (car cursor)) (planner-create-note current-page))))) (setq cursor (cdr cursor))) ;; Delete from pages removed from list (setq cursor links) (while cursor (unless (member (planner-link-base (car cursor)) old-pages) (planner-visit-link (planner-link-target (car links))) (save-restriction (when (planner-narrow-to-note) (delete-region (point-min) (point-max))))) (setq cursor (cdr cursor))) ;; Update the current note (planner-visit-link (concat (planner-note-page info) "#" (planner-note-anchor info))) (delete-region (1+ (point)) (planner-line-end-position)) (insert " " (planner-format-note info "" nil nil (planner-make-link new-links))) (planner-update-note)))) ad-do-it)) (defun planner-multi-note-delete () "Remove this note from all linked pages." (interactive) ;; Delete the current note. (save-window-excursion (let ((info (planner-current-note-info)) links) (when info (setq links (planner-multi-note-link-as-list info)) (while links (planner-visit-link (planner-link-target (car links))) (save-restriction (planner-narrow-to-note) (delete-region (point-min) (point-max))) (setq links (cdr links))))))) (defun planner-multi-note-delete-this-page () "Remove this note from the current page." (interactive) ;; Delete the current note. (save-window-excursion (let* ((info (planner-current-note-info)) new-link new-link-list) (when info (setq new-link-list (planner-multi-link-delete (planner-page-name) (planner-multi-note-link-as-list info))) (setq new-link (planner-multi-make-link new-link-list)) (save-restriction (planner-narrow-to-note) (delete-region (point-min) (point-max))) (while new-link-list (planner-visit-link (planner-link-target (car new-link-list))) (when (re-search-forward (concat "(" "\\(" muse-explicit-link-regexp "\\)" "\\(" (regexp-quote planner-multi-separator) "\\(" muse-explicit-link-regexp "\\)\\)+)") (planner-line-end-position) t) (replace-match (if (string= new-link "") "" (concat "(" new-link ")")) t t)) (setq new-link-list (cdr new-link-list))))))) (defalias 'planner-multi-xref-note 'planner-multi-note-xref) (defalias 'planner-multi-delete-note 'planner-multi-note-delete) (defalias 'planner-multi-delete-note-this-page 'planner-multi-note-delete-this-page) (defalias 'planner-multi-xref-task 'planner-multi-task-xref) (defalias 'planner-multi-delete-task-this-page 'planner-multi-task-delete-this-page) (defun planner-multi-read-name (file-alist &optional prompt initial) "Read multiple pages, completing based on FILE-ALIST. If PROMPT is specified, use that instead of \"Page:\"." (let* ((minibuffer-prompt-properties (plist-put (copy-sequence minibuffer-prompt-properties) 'read-only nil)) (completion-ignore-case t) (prompt (format "%s(default: %s) " (or prompt "Page: ") planner-default-page)) (crm-separator planner-multi-separator) (map (make-sparse-keymap)) (planner-multi-local-completion-map (progn (if (featurep 'crm) (set-keymap-parent map crm-local-completion-map) (set-keymap-parent map minibuffer-local-completion-map)) (define-key map planner-multi-separator 'self-insert-command) map)) str) (setq str (if (fboundp 'completing-read-multiple) (let ((crm-local-completion-map planner-multi-local-completion-map)) (completing-read-multiple prompt file-alist nil nil initial 'planner-history-list planner-default-page)) (let ((minibuffer-local-completion-map planner-multi-local-completion-map)) (planner-multi-split (read-string prompt initial 'planner-history-list planner-default-page))))) (cond ((or (null str) (string= (car str) "")) planner-default-page) ((string= (car str) "nil") nil) (t (mapconcat 'identity str planner-multi-separator))))) (defun planner-multi-read-name-multiple-prompts (file-alist prompt initial) "Read multiple pages, completing based on FILE-ALIST. If PROMPT is specified, use that instead of \"Page:\". Enter one plan page at a time. To end input, type \"nil\"." (let ((more t) input last list) (while more (setq input (planner-read-name-single file-alist (concat "nil to stop. " (or prompt "Page: ")) initial)) (setq planner-default-page nil initial nil) (if input (add-to-list 'list input t) (setq more nil))) (setq planner-default-page (planner-multi-make-link list)))) (if (fboundp 'completing-read-multiple) (setq planner-read-name-function 'planner-multi-read-name) (setq planner-read-name-function 'planner-multi-read-name-multiple-prompts)) ;;;###autoload (defun planner-multi-remove-task-from-pool (old-status new-status) "Remove completed tasks from `planner-multi-copy-tasks-to-page' if that still leaves them linked." (when (and planner-multi-copy-tasks-to-page (or (string= new-status "C") (string= new-status "X"))) (let ((info (planner-current-task-info))) (when (planner-task-link-text info) ;; If it is linked to TaskPool _and_ at least one other thing (cond ((string-match planner-multi-separator (planner-task-link-text info)) (let ((remove-from (mapcar 'planner-link-base (planner-multi-split planner-multi-copy-tasks-to-page))) new-links) (setq new-links (delq nil (mapcar (lambda (item) (unless (member (planner-link-base item) remove-from) (planner-link-base item))) (planner-multi-task-link-as-list info)))) (save-excursion (planner-replan-task (mapconcat 'identity new-links planner-multi-separator))) ;; Make sure we are on the same task (when (string= (planner-page-name) planner-multi-copy-tasks-to-page) (planner-find-file (car new-links)) (planner-find-task info)))) ;; Else if it has a date and is linked to TaskPool ((and (planner-task-date info) (string= (planner-task-plan info) planner-multi-copy-tasks-to-page) (save-excursion (planner-replan-task nil)) (when (string= (planner-page-name) planner-multi-copy-tasks-to-page) (planner-find-file (planner-task-date info)) (planner-find-task info)))))))) t) (add-hook 'planner-mark-task-hook 'planner-multi-remove-task-from-pool t) (provide 'planner-multi) ;;; planner-multi.el ends here planner-el/planner-notes-index.el000066400000000000000000000323521226462314700173430ustar00rootroot00000000000000;;; planner-notes-index.el --- Note indexing support for the Emacs planner ;; Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center ;;; Commentary: ;;;_+ Package description ;; Author: Sandra Jean Chua ;; Filename: planner-notes-index.el ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_+ Usage ;; ;; Place planner-notes-index.el in your load path and add this to your ;; .emacs: ;; ;; (require 'planner-notes-index) ;; ;; Then you can use tags of the form ;; ;; ;; ;; ;; ;; ;; ;; ;; You can also use the following interactive functions: ;; ;; planner-notes-index ;; planner-notes-index-days ;; planner-notes-index-weeks ;; planner-notes-index-months ;; planner-notes-index-years (wow!) ;; ;; These work based on the current date (date of current buffer, or today). ;; ;; If a single page is specified, this page is scanned for headlines ;; of the form: ;; ;; .#1 Headline ;; ;; and the results are presented as a bulleted list. ;; ;; If FROM and TO are specified, all date pages between them (inclusive) ;; are scanned. If FROM is omitted, it is assumed to be the earliest entry. ;; If TO is omitted, it is assumed to be the latest entry. ;; ;; If RECENT is specified, the list includes only that many recent headlines. ;; ;; and the results are presented as a bulleted list. ;; ;; To customize presentation, you can write a function that generates ;; the appropriate tags. You can also use ;; planner-extract-note-headlines in your own functions. ;;;_+ Contributors ;; Yann Hodique helped port this to Muse. (require 'planner) (require 'calendar) ;;; Code: ;;;_* Internal functions ;; Old names, but then planner-notes-get-headlines was created. ;; These may disappear. (defalias 'planner-notes-index-get-headlines 'planner-notes-index-headlines-on-page) (defalias 'planner-notes-index-get-headlines-range 'planner-notes-index-headlines-in-range) (defun planner-notes-index-headlines-on-page (page &optional limit) "Return a list of headlines in PAGE. If LIMIT is non-nil, only that many headlines are returned." (when (stringp limit) (setq limit (string-to-number limit))) (with-temp-buffer (insert-file-contents (planner-page-file page)) (planner-notes-get-headlines limit))) (defun planner-notes-index-headlines-in-range (&optional from to limit) "Return a list of headlines over a span of day pages. FROM (inclusive) and TO (inclusive) limit the dates. If FROM is nil, start from the earliest entry. If TO is nil, include the last entry. If LIMIT is non-nil, return at most LIMIT entries." (with-planner (when (and limit (stringp limit)) (setq limit (string-to-number limit))) (let ((pages (mapcar 'car (planner-get-day-pages from to))) data headlines) (while (and pages (if limit (> limit 0) t)) (setq data (planner-notes-index-headlines-on-page (car pages) limit)) (when limit (setq limit (- limit (length data)))) (when data (add-to-list 'headlines (cons (car pages) data) t)) (setq pages (cdr pages))) headlines))) (defun planner-notes-index-insert-as-list (page-headlines &optional limit prefix suffix) "Link and format PAGE-HEADLINES. PAGE-HEADLINES is a list of the form (page ((anchor headline) ...). If LIMIT is non-nil, only display that number of recent items. If PREFIX is non-nil, it is prepended to the item. If SUFFIX is non-nil, it is appended to the item." (when (and limit (stringp limit)) (setq limit (string-to-number limit))) (let ((page (car page-headlines))) (setq page-headlines (cdr page-headlines)) (while (and page-headlines (if limit (> limit 0) t)) (when prefix (insert prefix)) (insert (planner-make-link (concat page (caar page-headlines)) (cdr (car page-headlines)) t)) (when suffix (insert suffix)) (setq page-headlines (cdr page-headlines)) (when limit (setq limit (1- limit)))))) ;;;_* Emacs-wiki tags ;;;###autoload (defun planner-notes-index-tag (tag-beg tag-end attrs) "Mark up planner-notes-index tags. Tags can be of the form: " (let (last-month last-year) (mapc (lambda (item) (when (string-match planner-date-regexp (car item)) (unless (and last-year (string= (match-string 1 (car item)) last-year)) (insert "* " (setq last-year (match-string 1 (car item))) "\n\n")) (unless (and last-month (string= (match-string 2 (car item)) last-month)) (insert "** " last-year "." (setq last-month (match-string 2 (car item))) "\n\n"))) (insert "*** " (car item) "\n\n") (planner-notes-index-insert-as-list item nil " - " "\n") (insert "\n")) (if (assoc "page" attrs) (cons (cdr (assoc "page" attrs)) (planner-notes-index-headlines-on-page (cdr (assoc "page" attrs)) (cdr (assoc "limit" attrs)))) (planner-notes-index-headlines-in-range (cdr (assoc "from" attrs)) (cdr (assoc "to" attrs)) (cdr (assoc "limit" attrs))))))) ;;;###autoload (defun planner-notes-index-month-table-tag (beg end attrs) "Mark up a month note index. Tag is from BEG to END. ATTRS is a list of attributes. \"Month\" is a yyyy.mm string (default: current month). \"Limit\" is the maximum number of items per day (default: all). Examples: " (let ((month (cdr (assoc "month" attrs))) (limit (cdr (assoc "limit" attrs))) day headlines last dow) (unless month (setq month (substring (planner-get-current-date-filename) 0 7))) (when limit (setq limit (string-to-number limit))) (setq last (planner-filename-to-calendar-date (concat month ".31"))) (setq last (calendar-last-day-of-month (elt last 0) (elt last 2))) ;; Chronologically sorted, at least by day (setq headlines (nreverse (planner-notes-index-headlines-in-range (concat month ".01") (concat month ".31")))) ;; works ;; Offset to negative if month does not start on Sunday (setq day (- 1 (calendar-day-of-week (planner-filename-to-calendar-date (concat month ".01"))))) (setq dow 0) (insert "" "" "") (while (or (< day 31) (< day 6)) (when (= dow 0) (insert "")) (insert "") (when (= dow 6) (insert "")) (setq day (1+ day)) (setq dow (% (1+ dow) 7))) (insert "
    SunMonTueWedThuFriSat
    " (if (and (>= day 1) (<= day last)) (format (concat "[[%s" planner-date-separator "%02d]]") month day) "") "
    \n") (let ((data (assoc (format (concat "%s" planner-date-separator "%02d") month day) headlines)) extra) (planner-notes-index-insert-as-list data limit nil "
    ") (when (and limit data (> (length data) limit)) (setq extra (- (length data) limit)) (insert (format "%d more entr%s" extra (if (= extra 1) "y" "ies"))))) (insert "
    "))) ;;;_* Other user functions (defvar planner-notes-index-buffer "*Notes Index*" "Buffer for planner note index.") ;;;###autoload (defun planner-notes-index (&optional from to limit) "Display a clickable notes index. If called from a Lisp program, display only dates between FROM and TO. With a prefix arg LIMIT, display only that number of entries." (interactive "i i P") (when limit (setq limit (prefix-numeric-value limit))) (let ((headlines (planner-notes-index-headlines-in-range from to limit)) last-month last-year) (with-current-buffer (get-buffer-create planner-notes-index-buffer) (setq buffer-read-only nil) (erase-buffer) (cd (planner-directory)) (mapcar (lambda (item) (when (string-match planner-date-regexp (car item)) (unless (and last-year (string= (match-string 1 (car item)) last-year)) (insert "* " (setq last-year (match-string 1 (car item))) "\n\n")) (unless (and last-month (string= (match-string 2 (car item)) last-month)) (insert "** " last-year "." (setq last-month (match-string 2 (car item))) "\n\n"))) (insert "*** " (car item) "\n\n") (planner-notes-index-insert-as-list item nil " - " "\n") (insert "\n")) headlines) (planner-mode) (goto-char (point-min)) (pop-to-buffer (current-buffer))))) ;;;###autoload (defun planner-notes-index-days (days) "Display an index of notes posted over the past few DAYS. The list ends with the day of the current buffer or `planner-today'." (interactive (list (read-string "Number of days (1): " nil nil "1"))) (when (stringp days) (setq days (string-to-number days))) (planner-notes-index (planner-calculate-date-from-day-offset (planner-get-current-date-filename) (- 1 days)) (planner-get-current-date-filename))) ;;;###autoload (defun planner-notes-index-weeks (weeks) "Display an index of notes posted over the past few WEEKS. The list ends with the week of the current buffer or `planner-today'. Weeks start from Sunday." (interactive (list (read-string "Number of weeks (1): " nil nil "1"))) (when (stringp weeks) (setq weeks (string-to-number weeks))) (let ((date (planner-filename-to-calendar-date (planner-get-current-date-filename)))) (planner-notes-index (planner-date-to-filename (encode-time 0 0 0 (- (elt date 1) (calendar-day-of-week date) (* (- weeks 1) 7)) (elt date 0) (elt date 2))) (planner-get-current-date-filename)))) ;;;###autoload (defun planner-notes-index-months (months) "Display an index of notes posted over the past few MONTHS. The list ends with the month of the current buffer or `planner-today'." (interactive (list (read-string "Number of months (1): " nil nil "1"))) (when (stringp months) (setq months (string-to-number months))) (let ((date (planner-filename-to-calendar-date (planner-get-current-date-filename)))) (planner-notes-index (planner-date-to-filename (encode-time 0 0 0 1 (- (elt date 0) months -1) (elt date 2))) (planner-get-current-date-filename)))) ;;;###autoload (defun planner-notes-index-years (years) "Display an index of notes posted over the past few YEARS. The current year is included." (interactive (list (read-string "Number of years (1): " nil nil "1"))) (when (stringp years) (setq years (string-to-number years))) (let ((date (planner-filename-to-calendar-date (planner-today)))) (planner-notes-index (planner-date-to-filename (encode-time 0 0 0 1 1 (- (elt date 2) years -1))) (planner-get-current-date-filename)))) ;;;_* Initialization (add-hook 'muse-publish-markup-tags (if (featurep 'muse-nestable-tags) '("planner-notes-index" nil t nil planner-notes-index-tag) '("planner-notes-index" nil t planner-notes-index-tag))) (add-hook 'muse-publish-markup-tags (if (featurep 'muse-nestable-tags) '("planner-notes-index-month-table" nil t nil planner-notes-index-month-table-tag) '("planner-notes-index-month-table" nil t planner-notes-index-month-table-tag))) (provide 'planner-notes-index) ;;;_* Local emacs vars. ;; Local variables: ;; allout-layout: (* : ) ;; End: ;;; planner.el ends here planner-el/planner-psvn.el000066400000000000000000000122311226462314700160660ustar00rootroot00000000000000;;; planner-psvn.el --- psvn.el integration for the Emacs Planner ;; Copyright (C) 2005, 2006, 2008 Free Software Foundation, Inc. ;; Author: Stefan Reichör ;; Keywords: planner, psvn ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_ + Commentary: ;; This file allows you to refer to your svn changesets easily from within ;; a planner page. ;; ;; Example: the changeset ;; [[psvn://http://my.svn-repos.at/svn/project1/trunk@39][project1#39]] ;; can be shown easily via psvn. ;; ;; Additionally there is functionality to generate a note for your ;; commits via subversion, just set ;; `planner-psvn-log-edit-notice-commit-function' to t. ;;; Contributors: ;; Seth Falcon provided a patch to write the note to planner-today ;; rather than *temp*.muse. ;; Yann Hodique helped port this to Muse. ;;; Code: (require 'planner) (require 'psvn) (defgroup planner-psvn nil "Planner options for the psvn integration." :prefix "planner-psvn-" :group 'planner) (defcustom planner-psvn-log-edit-include-files-flag t "Non-nil means include a list of committed files in the note." :type 'boolean :group 'planner-psvn) (defcustom planner-psvn-log-edit-notice-commit-function nil "Function that should return non-nil if this commit should be noted. The function will be run in the log buffer." :type '(choice (const :tag "Always note commits" t) function) :group 'planner-psvn) ;; compatibility for older psvn.el revisions (cond ((fboundp 'svn-run) (defalias 'planner-svn-run 'svn-run)) ((fboundp 'svn-run-svn) (defalias 'planner-svn-run 'svn-run-svn)) (t (error "No `svn-run' command found"))) (defun planner-psvn-generate-url (repo-path revision &optional link-prefix no-link-postfix) (planner-make-link (concat "psvn://" repo-path "@" revision) (if link-prefix (if no-link-postfix link-prefix (concat link-prefix revision)) (concat "svn-rev#" revision)))) ;;;###autoload (defun planner-annotation-from-psvn () "If called from a psvn *svn-log-view* buffer, return an annotation. Suitable for use in `planner-annotation-functions'." (when (eq major-mode 'svn-log-view-mode) (svn-status-parse-info t) (planner-psvn-generate-url (svn-status-base-info->url) (svn-log-revision-at-point)))) ;;;###autoload (defun planner-psvn-browse-url (url) "If this is a psvn url, handle it." (when (string-match "\\`psvn:/?/?\\(.+\\)@\\([0-9]+\\)" url) (let ((repo-path (match-string 1 url)) (svn-rev (string-to-number (match-string 2 url))) (cur-buf (current-buffer))) (planner-svn-run nil t 'diff "diff" (concat repo-path "@" (number-to-string (- svn-rev 1))) (concat repo-path "@" (number-to-string svn-rev))) (svn-status-activate-diff-mode)) t)) (defun planner-psvn-log-edit-extract-file-name (file-info) (svn-status-line-info->filename file-info)) ;;;###autoload (defun planner-psvn-log-edit-add-note () "Add a note describing the commit via psvn to the current planner page." (when (if (functionp planner-psvn-log-edit-notice-commit-function) (funcall planner-psvn-log-edit-notice-commit-function) planner-psvn-log-edit-notice-commit-function) (svn-status-parse-info t) (save-window-excursion (planner-create-note nil) (insert "Commit") (insert (concat " " (planner-psvn-generate-url (svn-status-base-info->url) (number-to-string svn-status-commit-rev-number) (when svn-status-module-name (concat svn-status-module-name "#"))))) (newline) (when (and planner-psvn-log-edit-include-files-flag svn-status-files-to-commit) (insert "Files: ") (insert (mapconcat 'planner-psvn-log-edit-extract-file-name svn-status-files-to-commit " ")) (newline) (newline)) (insert-buffer-substring "*svn-log-edit*")))) (add-hook 'svn-log-edit-done-hook 'planner-psvn-log-edit-add-note) (planner-add-protocol "psvn:/?/?" 'planner-psvn-browse-url nil) (add-hook 'planner-annotation-functions 'planner-annotation-from-psvn) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-psvn) (provide 'planner-psvn) ;;; planner-psvn.el ends here planner-el/planner-publish.el000066400000000000000000000727201226462314700165570ustar00rootroot00000000000000;;; planner-publish.el --- planner-specific publishing ;; Copyright (C) 2005, 2006, 2008 Peter K. Lee ;; Parts copyright (C) 2005, 2008 Chris McMahan ;; Parts copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Dale P. Smith ;; Author: Peter K. Lee ;; Keywords: planner publish ;; Timestamp: 20 Jul 2005 10:05:29 ;; X-URL: http://www.corenova.com/... ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Introduction ;; Muse Styles for Planner: planner-xml, planner-html, planner-xhtml, etc. ;; Handles publishing of planner files. Works with Muse to generate ;; flexible markup. ;;; History: ;; 2005-07-15 (0.1) : creation date ;; 2005-07-20 (0.2) : first public release ;; 2005-07-21 (0.3) : added planner-html-style-sheet customize option ;; 2005-08-09 : added to Planner, see ChangeLog for further changes ;;; TODO: ;; add support for various PLANNER specific sections such as Diary, ;; Accomplishments, Timeclock, etc. ;;; Contributors: ;; Chris McMahan (cmcmahan AT one.net) helped notes to publish correctly. ;; Jim Ottaway fixed several bugs. ;; David Smith fixed a few bugs. ;; Dale Smith implemented a new version of the "notes" tag and ;; provided several patches. ;; Andrew J. Korty enabled multiple links with the "categories" ;; attribute. (require 'planner) (require 'muse-mode) (require 'muse-publish) (require 'muse-html) ;;; allow derive style from "html" and "xhtml" (require 'muse-xml) ;;; allow derive style from "xml" (unless (featurep 'muse-nested-tags) (error (concat "Your version of Muse is too old. Please upgrade to" " at least Muse 3.03."))) (defgroup planner-publish nil "Options controlling the behavior of PLANNER publishing. See `planner-publish' for more information." :group 'planner) (defcustom planner-publish-markup-regexps '((1275 "^#\\([A-C]\\)\\([0-9]*\\)\\s-*\\([_oXDCP]\\)\\s-*\\(.+\\)" 0 task) (1280 "^\\.#[0-9]+\\s-*" 0 note) (3200 planner-date-regexp 0 link)) "List of markup rules for publishing PLANNER. For more on the structure of this list, see `muse-publish-markup-regexps'." :type '(repeat (choice (list :tag "Markup rule" integer (choice regexp symbol) integer (choice string function symbol)) function)) :group 'planner-publish) (defcustom planner-publish-markup-functions '((task . planner-publish-markup-task) (note . planner-publish-markup-note)) "An alist of style types to custom functions for that kind of text. For more on the structure of this list, see `muse-publish-markup-functions'." :type '(alist :key-type symbol :value-type function) :group 'planner-publish) (defcustom planner-publish-markup-tags '(("nested-section" t nil t planner-publish-nested-section-tag) ("title" t t nil planner-publish-title-tag) ("content" t nil nil planner-publish-content-tag) ("diary-section" t nil nil planner-publish-diary-section-tag) ("tasks-section" t nil nil planner-publish-tasks-section-tag) ("notes-section" t nil nil planner-publish-notes-section-tag) ("notes" nil nil nil planner-publish-notes-tag) ("past-notes" nil t nil planner-publish-past-notes-tag) ("task" t t nil planner-publish-task-tag) ("note" t t nil planner-publish-note-tag)) "A list of tag specifications, for specially marking up PLANNER. See `muse-publish-markup-tags' for more information." :type '(repeat (list (string :tag "Markup tag") (boolean :tag "Expect closing tag" :value t) (boolean :tag "Parse attributes" :value nil) (boolean :tag "Nestable" :value nil) function)) :group 'planner-publish) ;;;_ + XML specific customizations (defcustom planner-xml-markup-strings '((planner-begin-nested-section . "
    ") (planner-end-nested-section . "
    ") (planner-begin-title . "") (planner-end-title . "") (planner-begin-content . "") (planner-end-content . "") (planner-begin-body . "") (planner-end-body . "") (planner-begin-diary-section . "") (planner-end-diary-section . "") (planner-begin-task-section . "") (planner-end-task-section . "") (planner-begin-task-body . "") (planner-end-task-body . "") (planner-begin-note-section . "") (planner-end-note-section . "") (planner-begin-task . "") (planner-end-task . "") (planner-begin-note . "") (planner-end-note . "") (planner-begin-note-details . "
    %s") (planner-end-note-details . "
    ") (planner-begin-note-link . "") (planner-end-note-link . "") (planner-begin-note-categories . "") (planner-end-note-categories . "")) "Strings used for marking up text as XML. These cover the most basic kinds of markup, the handling of which differs little between the various styles. If a markup rule is not found here, `muse-xml-markup-strings' is searched." :type '(alist :key-type symbol :value-type string) :group 'planner-publish) (defcustom planner-xml-header "(muse-xml-encoding)
    \"?> <lisp>(muse-publishing-directive \"title\")</lisp> (muse-publishing-directive \"author\") (muse-style-element :maintainer) (muse-publishing-directive \"date\") \n" "Header used for publishing PLANNER XML files. This may be text or a filename." :type 'string :group 'planner-publish) (defcustom planner-xml-footer " \n" "Footer used for publishing PLANNER XML files. This may be text or a filename." :type 'string :group 'planner-publish) ;;;_ + HTML specific customizations (defcustom planner-html-markup-strings '((planner-begin-nested-section . "
    ") (planner-end-nested-section . "
    ") (planner-begin-title . "") (planner-end-title . "") (planner-begin-content . "
    ") (planner-end-content . "
    ") (planner-begin-body . "
    ") (planner-end-body . "
    ") (planner-begin-diary-section . "
    ") (planner-end-diary-section . "
    ") (planner-begin-task-section . "
    ") (planner-end-task-section . "
    ") (planner-begin-task-body . "
      ") (planner-end-task-body . "
    ") (planner-begin-note-section . "
    ") (planner-end-note-section . "
    ") (planner-begin-task . "
  • %s") (planner-end-task . "
  • ") (planner-begin-note . "
    %s") (planner-end-note . "
    ") (planner-begin-note-details . "
    %s") (planner-end-note-details . "
    ") (planner-begin-note-link . " ") (planner-end-note-link . "") (planner-begin-note-categories . " ") (planner-end-note-categories . "")) "Strings used for marking up text as HTML. These cover the most basic kinds of markup, the handling of which differs little between the various styles. If a markup rule is not found here, `muse-html-markup-strings' is searched." :type '(alist :key-type symbol :value-type string) :group 'planner-publish) (defcustom planner-html-style-sheet "" "Store your stylesheet definitions here. The provided default is for reference only. You definitely want to customize this for your particular needs & wants. This is used in `planner-html-header' and `planner-xhtml-header'. Refer to `muse-html-style-sheet' for details on usage. You may simply override the above by specifying an explicit link to a CSS file." :type 'string :group 'planner-publish) (defcustom planner-html-header " <lisp> (concat (muse-publishing-directive \"title\") (let ((author (muse-publishing-directive \"author\"))) (if (not (string= author (user-full-name))) (concat \" (by \" author \")\"))))</lisp> muse-html-meta-http-equiv\" content=\"muse-html-meta-content-type\"> (let ((maintainer (muse-style-element :maintainer))) (when maintainer (concat \"\"))) planner-html-style-sheet

    (concat (muse-publishing-directive \"title\") (let ((author (muse-publishing-directive \"author\"))) (if (not (string= author (user-full-name))) (concat \" (by \" author \")\"))))

    planner-html-inner-header
    \n" "Header used for publishing PLANNER HTML files. This may be text or a filename." :type 'string :group 'planner-publish) (defcustom planner-html-footer "
    planner-html-inner-footer
    \n" "Footer used for publishing PLANNER HTML files. This may be text or a filename." :type 'string :group 'planner-publish) (defcustom planner-xhtml-header " (muse-html-encoding)\"?> <lisp> (concat (muse-publishing-directive \"title\") (let ((author (muse-publishing-directive \"author\"))) (if (not (string= author (user-full-name))) (concat \" (by \" author \")\"))))</lisp> muse-html-meta-http-equiv\" content=\"muse-html-meta-content-type\" /> (let ((maintainer (muse-style-element :maintainer))) (when maintainer (concat \"\"))) planner-html-style-sheet

    (concat (muse-publishing-directive \"title\") (let ((author (muse-publishing-directive \"author\"))) (if (not (string= author (user-full-name))) (concat \" (by \" author \")\"))))

    planner-html-inner-header
    \n" "Header used for publishing PLANNER XHTML files. This may be text or a filename." :type 'string :group 'planner-publish) (defcustom planner-xhtml-footer "
    planner-html-inner-footer
    \n" "Footer used for publishing PLANNER XHTML files. This may be text or a filename." :type 'string :group 'planner-publish) (defcustom planner-html-inner-header "" "Extra header section that can be embedded within `planner-html-header' and `planner-xhtml-header'." :type 'string :group 'planner-publish) (defcustom planner-html-inner-footer "" "Extra footer section that can be embedded within `planner-html-footer' and `planner-xhtml-footer'." :type 'string :group 'planner-publish) ;;;_ + Publishing hooks (defcustom planner-publish-prepare-regexps '((100 "^\\(\\*+\\)\\s-+" 0 planner-publish-section)) "List of markup rules to apply before publishing a page with Planner. See `muse-publish-markup-regexps' for details on the syntax used." :type '(repeat (choice (list :tag "Markup rule" integer (choice regexp symbol) integer (choice string function symbol)) function)) :group 'planner-publish) (defcustom planner-publish-finalize-regexps '() "List of markup rules to apply after publishing a page with Planner. See `muse-publish-markup-regexps' for details on the syntax used." :type '(repeat (choice (list :tag "Markup rule" integer (choice regexp symbol) integer (choice string function symbol)) function)) :group 'planner-publish) (defun planner-publish-prepare-buffer () (goto-char (point-min)) (muse-publish-markup "preparing Planner page" planner-publish-prepare-regexps) ;; indicate that we are to continue preparing the buffer nil) (defun planner-publish-finalize-buffer () (goto-char (point-min)) (muse-publish-markup "finalizing Planner page" planner-publish-finalize-regexps) ;; indicate that we are to continue finalizing the buffer nil) ;;;_ + Markup (defvar planner-publish-ignore-url-desc-specials nil "If non-nil, do not escape specials in URL descriptions.") (defun planner-publish-decide-specials (context) "Determine the specials to escape for Planner, depending on CONTEXT." (if (and (eq context 'url-desc) planner-publish-ignore-url-desc-specials) nil (muse-xml-decide-specials context))) (defun planner-publish-markup-task () "Replace tasks with XML representation of task data." (save-restriction (narrow-to-region (planner-line-beginning-position) (planner-line-end-position)) (let ((info (planner-current-task-info))) (delete-region (point-min) (point-max)) (forward-line 1) (insert (format (concat "") (or (planner-task-number info) "") (or (planner-task-priority info) "") (or (planner-publish-task-status-expand (planner-task-status info)) "") (or (planner-task-link-text info) "") (or (planner-task-plan info) "") (or (planner-task-date info) ""))) ;; mark this area read only for safety's sake (planner-insert-markup (planner-task-description info)) (insert "")))) (defun planner-publish-markup-note () "Replace note with XML representation of note data. Borrowed heavily from Sacha's personal configs." (save-restriction (narrow-to-region (save-excursion (beginning-of-line) (point)) (or (save-excursion (and (re-search-forward "^\\(\\.#\\|* \\|\\)" nil t) (match-beginning 0))) (point-max))) (let ((info (planner-current-note-info t))) (delete-region (point-min) (point-max)) (insert (format (concat "") (planner-note-anchor info) (or (planner-note-timestamp info) "") (or (planner-note-link info) "") (or (planner-note-link-text info) "")) "" (planner-note-title info) "\n" "\n") (planner-insert-markup (planner-note-body info)) (insert "\n\n\n\n")))) ;;;_ + Tags (defun planner-insert-markup (&rest args) (if (fboundp 'muse-insert-markup) (apply 'muse-insert-markup args) (let ((beg (point))) (apply 'insert args) (muse-publish-mark-read-only beg (point))))) (defun planner-publish-nested-section-tag (beg end) "Generated by `planner-publish-section', the nested section tag now takes in TITLE and LEVEL attributes. This is related to the Muse concept of sections, but done before marking up the buffer, and with special actions done on the title of each section." (save-excursion (goto-char beg) (planner-insert-markup (muse-markup-text 'planner-begin-nested-section)) (goto-char end) (planner-insert-markup (muse-markup-text 'planner-end-nested-section)))) (defun planner-publish-title-tag (beg end attrs) (let ((level (cdr (assoc "level" attrs)))) (save-excursion (goto-char beg) (planner-insert-markup (muse-markup-text 'planner-begin-title level)) (goto-char end) (planner-insert-markup (muse-markup-text 'planner-end-title level))))) (defun planner-publish-content-tag (beg end) (save-excursion (goto-char end) (planner-insert-markup (muse-markup-text 'planner-end-content)) (goto-char beg) (planner-insert-markup (muse-markup-text 'planner-begin-content)))) (defun planner-publish-diary-section-tag (beg end) (save-excursion (goto-char beg) (planner-insert-markup (muse-markup-text 'planner-begin-diary-section)) (forward-line 1) (muse-publish-verse-tag (point) end) (goto-char end) (insert "\n") (planner-insert-markup (muse-markup-text 'planner-end-diary-section)))) (defun planner-publish-tasks-section-tag (beg end) (save-excursion (goto-char beg) (planner-insert-markup (muse-markup-text 'planner-begin-task-section)) (forward-line 1) (planner-insert-markup (muse-markup-text 'planner-begin-task-body)) (goto-char end) (planner-insert-markup (muse-markup-text 'planner-end-task-body)) (planner-insert-markup (muse-markup-text 'planner-end-task-section)))) (defun planner-publish-task-tag (beg end attrs) (save-excursion (let ((number (cdr (assoc "id" attrs))) (status (cdr (assoc "status" attrs))) (priority (cdr (assoc "priority" attrs))) (link (cdr (assoc "link" attrs))) (plan (cdr (assoc "plan" attrs))) (date (cdr (assoc "date" attrs)))) (remove-text-properties beg end '(read-only nil rear-nonsticky nil)) (goto-char end) (when link (insert " (" (planner-make-link link) ")")) (planner-insert-markup (muse-markup-text 'planner-end-task)) (goto-char beg) (planner-insert-markup (muse-markup-text 'planner-begin-task status priority (if planner-use-task-numbers (concat priority number) (concat priority (number-to-string (random 134217727)))) (concat priority number " " (planner-publish-task-status-collapse status) " ")))))) (defun planner-publish-notes-section-tag (beg end) "Replace the region BEG to END with the notes for this page." (save-excursion (planner-insert-markup (muse-markup-text 'planner-begin-note-section)) (forward-line 1) (planner-insert-markup (muse-markup-text 'planner-begin-body)) (insert ?\n) (goto-char end) (planner-insert-markup (muse-markup-text 'planner-end-body)) (planner-insert-markup (muse-markup-text 'planner-end-note-section)))) (defun planner-publish-notes-tag (beg end) "Replace the region BEG to END with an index of the notes for this page." (delete-region beg end) (insert "\n") (mapcar (lambda (item) (insert (format " - [[%s%s][%s]]\n" (planner-page-name) (car item) (planner-remove-links (cdr item))))) (save-excursion (find-file muse-publishing-current-file) (planner-notes-get-headlines))) (insert "\n")) (defun planner-publish-past-notes-tag (beg end attrs) "Replace the region BEG to END with an index of past notes. If ATTRS is non-nil, it is an alist containing values for DIRECTORY and START." (let ((files (save-excursion (find-file muse-publishing-current-file) (planner-get-day-pages nil nil t))) (earliest (cdr (assoc "start" attrs)))) (while files (when (or (null earliest) (not (string-lessp (caar files) earliest))) (let ((title-lines (list t))) (with-temp-buffer (insert-file-contents (cdar files)) (while (re-search-forward "^\\.#\\([0-9]+\\)\\s-+\\(.+\\)" nil t) (nconc title-lines (list (cons (match-string 1) (match-string 2)))))) (setq title-lines (cdr title-lines)) (when title-lines (insert (planner-make-link (planner-page-name (caar files))) " ::\n") (planner-insert-markup "
    \n") (while title-lines (planner-insert-markup "
    ") (insert (format "[[%s#%s][%s]]" (planner-page-name (caar files)) (caar title-lines) (cdar title-lines))) (planner-insert-markup "
    \n") (setq title-lines (cdr title-lines))) (planner-insert-markup "
    \n\n")))) (setq files (cdr files))))) (defun planner-publish-note-tag (beg end attrs) (save-excursion (let ((anchor (or (cdr (assoc "anchor" attrs)) "")) (timestamp (or (cdr (assoc "timestamp" attrs)) "")) (link (or (cdr (assoc "link" attrs)) "")) (categories (or (cdr (assoc "categories" attrs)) ""))) (remove-text-properties beg end '(read-only nil rear-nonsticky nil)) (goto-char beg) (planner-insert-markup (muse-markup-text 'planner-begin-note anchor (concat "#" anchor))) (goto-char end) (planner-insert-markup (muse-markup-text 'planner-begin-note-details timestamp) (muse-markup-text 'planner-begin-note-link)) (insert link) (planner-insert-markup (muse-markup-text 'planner-end-note-link)) ;; remove link item from categories to avoid duplicates (unless (or (string= link "") (string= categories "")) (setq categories (planner-replace-regexp-in-string (regexp-quote link) "" categories t t))) (planner-insert-markup (muse-markup-text 'planner-begin-note-categories)) (insert categories) (planner-insert-markup (muse-markup-text 'planner-end-note-categories)) (insert ?\n) (planner-insert-markup (muse-markup-text 'planner-end-note-details)) (planner-insert-markup (muse-markup-text 'planner-end-note))))) ;;;_ + helper routine (defun planner-publish-task-status-expand (status) (cond ((string= status "_") "open") ((string= status "o") "in-progress") ((string= status "D") "delegated") ((string= status "P") "pending") ((string= status "X") "done") ((string= status "C") "cancelled") (t "unknown"))) (defun planner-publish-task-status-collapse (status) (cond ((string= status "open") "_") ((string= status "in-progress") "o") ((string= status "delegated") "D") ((string= status "pending") "P") ((string= status "done") "X") ((string= status "cancelled") "C") (t "?"))) (defun planner-publish-section-close (depth text) "Find where the closing tag of DEPTH should go, and insert TEXT." (let (not-end) (save-excursion (while (and (setq not-end (re-search-forward (concat "^\\*\\{1," (number-to-string depth) "\\}\\s-+") nil t)) (get-text-property (match-beginning 0) 'read-only))) (if not-end (forward-line 0) (goto-char (point-max))) (cond ((not (eq (char-before) ?\n)) (insert "\n\n")) ((not (eq (char-before (1- (point))) ?\n)) (insert "\n"))) (insert text) (insert "\n")))) (defvar planner-section-tagnames '(("Diary" . "diary-section") ("Tasks" . "tasks-section") ("Notes" . "notes-section")) "Alist of sections and their tag name.") (defun planner-publish-section-tagname (text) "A routine that checks `planner-section-tagnames' for tagname." (let ((tagname (cdr (assoc text planner-section-tagnames)))) (if tagname tagname "nested-section"))) (defun planner-publish-section () "Publish the current heading as a section." (let* ((depth (length (match-string 1))) (title (buffer-substring (match-end 0) (planner-line-end-position))) (tagname (planner-publish-section-tagname title))) (delete-region (match-beginning 0) (match-end 0)) (insert (format "<%s level=\"%s\">" tagname depth (1+ depth))) (end-of-line) (insert "") (planner-publish-section-close depth (format "" tagname)))) ;;;_ + Planner Style Definitions (muse-derive-style "planner-xml" "xml" :regexps 'planner-publish-markup-regexps :functions 'planner-publish-markup-functions :tags 'planner-publish-markup-tags :specials 'planner-publish-decide-specials :strings 'planner-xml-markup-strings :before 'planner-publish-prepare-buffer :after 'planner-publish-finalize-buffer :header 'planner-xml-header :footer 'planner-xml-footer) (muse-derive-style "planner-html" "html" :regexps 'planner-publish-markup-regexps :functions 'planner-publish-markup-functions :tags 'planner-publish-markup-tags :specials 'planner-publish-decide-specials :strings 'planner-html-markup-strings :before 'planner-publish-prepare-buffer :after 'planner-publish-finalize-buffer :header 'planner-html-header :footer 'planner-html-footer) (muse-derive-style "planner-xhtml" "xhtml" :regexps 'planner-publish-markup-regexps :functions 'planner-publish-markup-functions :tags 'planner-publish-markup-tags :specials 'planner-publish-decide-specials :strings 'planner-html-markup-strings :before 'planner-publish-prepare-buffer :after 'planner-publish-finalize-buffer :header 'planner-xhtml-header :footer 'planner-xhtml-footer) (provide 'planner-publish) ;;; planner-publish.el ends here planner-el/planner-rank.el000066400000000000000000000436611226462314700160460ustar00rootroot00000000000000;;; planner-rank.el --- Importance vs Urgency for the Emacs planner ;; ;; Copyright (C) 2005, 2008 Dryice Dong Liu . All rights reserved. ;; Parts copyright (C) 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center ;; Keywords: emacs planner important emergent rank deadline ;; Author: Dryice Liu ;; Description: calculate task rank from importance and urgency ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file models Franklin Covey's Urgency and Importance ;; principle. Where for both Urgency and Importance, you can measure ;; them with number 0-9. 9 means "I should have done this from ;; Emergency/Important point of view" while 0 means "I can forget this ;; from Emergency/Important point of view". ;; ;; If you use the planner-deadline feature, the Urgency value is ;; calculated from how many days left to meet the deadline. You can ;; manipulate `planner-rank-deadline-urgency-map-list' if you have ;; speal needs. ;; ;; The rank is calculated from Urgency and Importance. You can choose ;; your favoriate algorithm by setting ;; `planner-rank-rank-calculate-function'. Took a look at the ;; planner-rank-calculate-rank-* functions to see which one you like ;; most. Call `planner-rank-test-algorithm' to get the result tables ;; and see how it works. ;; ;; The three planner-sort-tasks-by-* functions in this file is ;; suitable for `planner-sort-tasks-key-function'. ;; ;; if you want to set rank for every new task, add ;; ;; (add-hook 'planner-create-task-from-buffer-hook 'planner-rank-change) ;; ;; to your .emacs. ;;; TODO ;; - planner-timeclock-summary.el integration ;;; Code: (require 'planner) (require 'planner-deadline) ;;; USER VARIABLES ----------------------------------------------------------- (defgroup planner-rank nil "Importance vs Urgency support for planner.el." :prefix "planner-rank" :group 'planner) (defcustom planner-rank-change-hook nil "Functions to run after `planner-rank-change'. Point will be on the same line as the task." :type 'hook :group 'planner-rank) (defcustom planner-rank-priority-A-valve 6 "\"A\" \"B\" task valve. Tasks with rank greater than or equal to this value will be in priority A." :type 'number :group 'planner-rank) (defcustom planner-rank-priority-B-valve 3 "\"B\" \"C\" task valve. Tasks with rank greater than or equal to this value and less than `planner-rank-priority-A-valve' will be in priority B. Tasks with rank less than this value will be in priority C." :type 'number :group 'planner-rank) (defcustom planner-rank-deadline-urgency-map-list '(-1 0 3 7 14 21 30 90 365) "Deadline to Urgency map. If there is a deadline for the task, the urgency value is calculated from how many days left and this list. E.g, there's n days left, if n is less or equal than nth 0 of this list, it will get urgency 9. If it's greater than nth 0, but less or equal than nth 1, it will be urgency 8. It's the user's responsibility to keep the list in order. The meaning of the default value: +-------------+---------+ |Days left |Urgency | +-------------+---------+ |overdue |9 | |today |8 | |3 days |7 | |a week |6 | |2 weeks |5 | |3 weeks |4 | |this month |3 | |this quarter |2 | |this year |1 | |longer |0 | +-------------+---------+" :type '(repeat integer) :group 'planner-rank) (defcustom planner-rank-default-importance 5 "Default importance value for newly added rank." :type 'integer :group 'planner-rank) (defcustom planner-rank-default-urgency 5 "Default urgency value for newly added rank." :type 'integer :group 'planner-rank) (defcustom planner-rank-importance-vs-urgency-factor 1.5 "The weight of importance vs urgency. How much do you think importance is more \"important\" than urgency. This will be used in planner-rank-calculate-rank-weighted-* functions." :type 'number :group 'planner-rank) (defcustom planner-rank-rank-calculate-function 'planner-rank-calculate-rank-weighted-rmsd "Define the function called to calculate rank. The function should take two arguments: the importance and the urgency value, and return the calculated rank value." :type 'function :group 'planner-rank) (defcustom planner-rank-test-buffer "*Planner Rank Test Result*" "Buffer name for timeclock reports from `planner-rank-test-algorithm'." :type 'string :group 'planner-rank) ;;;_+ Internal variables and utility functions (add-hook 'planner-deadline-change-hook 'planner-rank-update-current-task) (defconst planner-rank-regexp "\\(\\s-*{{Rank:\\s-+\\([0-9][\\.\\-][0-9]+\\)\\s-+-\\s-+I=\\([0-9]\\)\\s-+U=\\([0-9]\\)}}\\)" "Regular expression for rank data. Regexp group 1 is the whole rank string. Regexp group 2 is the rank value. Regexp group 3 is the importance value. Regexp group 4 is the urgency value.") (defun planner-rank-get-task-info () "Get the rank of the current task. Return nil if there's no rank string in the current task." (save-excursion (let ((string (buffer-substring (planner-line-beginning-position) (planner-line-end-position)))) (when (string-match planner-rank-regexp string) (list (string-to-number (planner-match-string-no-properties 2 string)) (string-to-number (planner-match-string-no-properties 3 string)) (string-to-number (planner-match-string-no-properties 4 string))))))) (defsubst planner-rank-rank (info) "Return the rank of a task given INFO." (nth 0 info)) (defsubst planner-rank-importance (info) "Return the importance of a task given INFO." (nth 1 info)) (defsubst planner-rank-urgency (info) "Return the urgency of a task given INFO." (nth 2 info)) (defun planner-rank-calculate-base (arg) "Get the base of importance or urgency. ARG is the basic priority." (cond ((>= arg planner-rank-priority-A-valve) planner-rank-priority-A-valve) ((>= arg planner-rank-priority-B-valve) planner-rank-priority-B-valve) (t 0))) (defun planner-rank-calculate-rank-average (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. The algorithm is a simple average. Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-average\)" (/ (+ importance urgency) 2.0)) (defun planner-rank-calculate-rank-average-aggressive (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. The algorithm is a simple average. Plus making sure the result is close to the higher value. Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-average-aggressive\)" (let ((average (/ (+ importance urgency) 2.0))) (max average (planner-rank-calculate-base importance) (planner-rank-calculate-base urgency)))) (defun planner-rank-calculate-rmsd (a b) "Return the root mean square deviation of A and B." (sqrt (/ (+ (* a a) (* b b)) 2.0))) (defun planner-rank-calculate-rank-rmsd (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. The algorithm is the root mean square deviation of importance and urgency. Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-rmsd\)" (planner-rank-calculate-rmsd importance urgency)) (defun planner-rank-calculate-rank-rmsd-aggressive (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. The algorithm is the RMDS first, if it's smaller than the base of the bigger arg, return sqrt(RMDS) + base. Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-rmsd-aggressive\)" (let ((base (planner-rank-calculate-base (max importance urgency))) (rmsd (planner-rank-calculate-rmsd importance urgency))) (if (< rmsd base) (+ base (sqrt rmsd)) rmsd))) (defun planner-rank-calculate-rank-aggressive-rmsd-rest (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. First we make sure the result is bigger than base, then we add (sqrt(rmsd rest smaller)). Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-aggressive-rmsd-rest\)" (let* ((bigger (max importance urgency)) (smaller (min importance urgency)) (base (planner-rank-calculate-base bigger))) (+ base (sqrt (planner-rank-calculate-rmsd smaller (- bigger base)))))) (defun planner-rank-calculate-rank-aggressive-rmsd-full (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. First we make sure the result is bigger than base, then we add (sqrt(rmsd bigger smaller)). Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-aggressive-rmsd-full\)" (let* ((bigger (max importance urgency)) (smaller (min importance urgency)) (base (planner-rank-calculate-base bigger))) (+ base (sqrt (planner-rank-calculate-rmsd smaller bigger))))) (defun planner-rank-calculate-rank-average-base-rmsd (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. The average of two base plus rmsd. Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-average-base-rmsd\)" (+ (/ (+ (planner-rank-calculate-base importance) (planner-rank-calculate-base urgency)) 2.0) (sqrt (planner-rank-calculate-rmsd importance urgency)))) (defun planner-rank-calculate-rank-weighted-average (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. The weighted average. Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-weighted-average\)" (/ (+ (* importance planner-rank-importance-vs-urgency-factor) urgency) (+ planner-rank-importance-vs-urgency-factor 1.0))) (defun planner-rank-calculate-rank-weighted-rmsd (importance urgency) "Calculate the rank from IMPORTANCE and URGENCY. The weighted rmsd. Eval the following sexp to see how it works: \(planner-rank-test-algorithm 'planner-rank-calculate-rank-weighted-rmsd\)" (sqrt (/ (+ (* planner-rank-importance-vs-urgency-factor planner-rank-importance-vs-urgency-factor importance importance) (* urgency urgency)) (+ (* planner-rank-importance-vs-urgency-factor planner-rank-importance-vs-urgency-factor) 1.0)))) (defun planner-rank-calculate-urgency-from-deadline (days) "Calculate urgency from how many DAYS are left." (let ((list planner-rank-deadline-urgency-map-list) value) (while list (if (<= days (car list)) (setq value (prog1 (length list) (setq list nil))) (setq list (cdr list)))) value)) (defun planner-rank-calculate-rank (importance urgency) "Make sure the rank is not greater than 9, just in case. This is based on IMPORTANCE and URGENCY." (min (funcall planner-rank-rank-calculate-function importance urgency) 9)) (defun planner-rank-calculate-priority-from-rank (rank) "Calculate task priority (A,B,C) from RANK." (cond ((>= rank planner-rank-priority-A-valve) "A") ((>= rank planner-rank-priority-B-valve) "B") (t "C"))) (defun planner-rank-read-importance-and-urgency () "Read importance and urgency. Use old value as default if available." (let ((rank-info (planner-rank-get-task-info)) (task-info (planner-current-task-info)) (old-importance planner-rank-default-importance) (old-urgency planner-rank-default-urgency) (deadline (planner-deadline-get-current-deadline)) new-importance new-urgency) (if rank-info (progn (setq old-importance (planner-rank-importance rank-info)) (setq old-urgency (planner-rank-urgency rank-info)))) (setq new-importance (string-to-number (read-string "Importance: " nil nil (number-to-string old-importance)))) (if deadline (setq new-urgency (planner-rank-calculate-urgency-from-deadline (planner-deadline-days-left deadline task-info))) (setq new-urgency (string-to-number (read-string "Urgency: " nil nil (number-to-string old-urgency))))) (list new-importance new-urgency))) ;;;###autoload (defun planner-sort-tasks-by-rank () "Sort tasks by status (_PDXC), priority (ABC), and rank. Suitable for `planner-sort-tasks-key-function'" (skip-chars-forward "#ABC") (let ((case-fold-search t) (ch (char-before)) status) (skip-chars-forward "0123456789 ") (setq status (char-after)) (+ ;(read (current-buffer)) (cond ((eq status ?P) 1000) ((eq status ?D) 2000) ((eq status ?X) 3000) ((eq status ?C) 4000) (t 0)) (cond ((eq ch ?A) 100) ((eq ch ?B) 200) ((eq ch ?C) 300)) (if (planner-rank-rank (planner-rank-get-task-info)) (* 10 (- 10 (planner-rank-rank (planner-rank-get-task-info)))) 99)))) ;;;###autoload (defun planner-sort-tasks-by-importance () "Sort tasks by status (_PDXC), priority (ABC), and importance. Suitable for `planner-sort-tasks-key-function'" (skip-chars-forward "#ABC") (let ((case-fold-search t) (ch (char-before)) status) (skip-chars-forward "0123456789 ") (setq status (char-after)) (+ ;(read (current-buffer)) (cond ((eq status ?P) 1000) ((eq status ?D) 2000) ((eq status ?X) 3000) ((eq status ?C) 4000) (t 0)) (cond ((eq ch ?A) 100) ((eq ch ?B) 200) ((eq ch ?C) 300)) (if (planner-rank-importance (planner-rank-get-task-info)) (* 10 (- 10 (planner-rank-importance (planner-rank-get-task-info)))) 99)))) ;;;###autoload (defun planner-sort-tasks-by-urgency () "Sort tasks by status (_PDXC), priority (ABC), and urgency. Suitable for `planner-sort-tasks-key-function'" (skip-chars-forward "#ABC") (let ((case-fold-search t) (ch (char-before)) status) (skip-chars-forward "0123456789 ") (setq status (char-after)) (+ ;(read (current-buffer)) (cond ((eq status ?P) 1000) ((eq status ?D) 2000) ((eq status ?X) 3000) ((eq status ?C) 4000) (t 0)) (cond ((eq ch ?A) 100) ((eq ch ?B) 200) ((eq ch ?C) 300)) (if (planner-rank-urgency (planner-rank-get-task-info)) (* 10 (- 10 (planner-rank-urgency (planner-rank-get-task-info)))) 99)))) ;; for developer (defun planner-rank-test-algorithm (test-function) "Make a test result table for the given TEST-FUNCTION." (interactive "aTest function: ") (switch-to-buffer (get-buffer-create planner-rank-test-buffer)) (erase-buffer) (insert (format "Result table for function \`%s\'\n\n\n" test-function)) (let ((row 0) (column 0)) (insert " |") (while (< column 10) (insert (format "%3d |" column)) (setq column (1+ column))) (insert " -> Importance\n") (while (< row 10) (insert (format "%4d |" row)) (setq column 0) (while (< column 10) (insert (format "%.2f |" (funcall test-function column row))) (setq column (1+ column))) (insert "\n") (setq row (1+ row))) (insert "\n |\n V\nUrgency"))) ;; user visible functions ;;;###autoload (defun planner-rank-change (&optional importance urgency) "Change the IMPORTANCE and URGENCY of the current task. If there's deadline available, calculate urgency instead of asking the user." (interactive) (unless (and importance urgency) (let ((temp (planner-rank-read-importance-and-urgency))) (setq importance (car temp)) (setq urgency (cadr temp)))) (save-excursion (save-match-data (let* ((info (planner-current-task-info)) (old-description (planner-task-description info)) (old-priority (planner-task-priority info)) (rank (planner-rank-calculate-rank importance urgency)) (new-priority (planner-rank-calculate-priority-from-rank rank)) new-description) (if info (progn (if (not (string= old-priority new-priority)) (planner-set-task-priority new-priority)) (if (string-match planner-rank-regexp old-description) (setq new-description (replace-match "" t t old-description)) (setq new-description old-description)) (planner-edit-task-description (format "%s {{Rank: %.2f - I=%d U=%d}}" new-description rank importance urgency)) (run-hooks 'planner-rank-change-hook))))))) ;;;###autoload (defun planner-rank-update-current-task () "Re-calculate rank for the current task." (interactive) (let* ((task-info (save-match-data (planner-current-task-info))) (status (planner-task-status task-info)) (deadline (planner-deadline-get-current-deadline)) (rank-info (planner-rank-get-task-info)) (importance (planner-rank-importance rank-info)) (urgency (planner-rank-urgency rank-info))) (when (and deadline task-info (not (equal status "X")) (not (equal status "C"))) (setq urgency (planner-rank-calculate-urgency-from-deadline (planner-deadline-days-left deadline task-info))) (planner-rank-change importance urgency)))) ;;;###autoload (defun planner-rank-update-all () "Re-calculate rank for all tasks in the current page." (interactive) (save-excursion (save-restriction (when (planner-narrow-to-section 'tasks) (goto-char (point-min)) (while (re-search-forward planner-rank-regexp nil t) (save-match-data (planner-rank-update-current-task)) (forward-line 1)))))) (provide 'planner-rank) ;;; planner-rank.el ends here ;; ;; Local Variables: ;; indent-tabs-mode: t ;; tab-width: 8 ;; End: planner-el/planner-rdf.el000066400000000000000000000656761226462314700157000ustar00rootroot00000000000000;;; planner-rdf.el --- RDF export for Emacs PlannerMode ;; Copyright (C) 2004, 2008 Rainer Volz ;; Parts copyright (C) 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center ;; Author: Rainer Volz, http://www.rainervolz.de ;; Version: 0.1 ;; Keywords: PlannerMode OWL RDF ;; X-URL: not distributed yet ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; planner-rdf is an add-on to Planner. It provides functions to ;; publish Planner information in RDF format, so that the Planner ;; information can be processed in an automated way by RDF-aware ;; tools. To do this planner-rdf adds itself to the hook ;; muse-after-publish-hook, which is run whenever Planner pages are ;; being published. ;; The source distribution and the HTML edition of the documentation is ;; available at http://www.rainervolz.de/planner-rdf/ ;; To use planner-rdf put this file into your load-path and the following into ;; your ~/.emacs file: ;; (require 'planner-rdf) ;; (add-hook 'muse-after-publish-hook 'planner-rdf-publish-file) ;; (add-hook 'muse-after-publish-hook 'planner-rdf-publish-index) ;; To minimise interference with the publication of other (non-Planner) ;; Muse projects, planner-rdf-publish-file checks whether the current ;; major mode is planner-mode. If yes, RDF publication is started, if not, the ;; file is ignored. ;; planner-rdf creates two files for every published Planner file: a .rdf and ;; a .owl file. The .owl file contains ;; - tasks ;; - notes ;; of the respective Planner page in OWL format. The OWL schema used is ;; documented in planner-rdf.owl, which is part of this distribution. ;; For a detailed explanation of the format please look at the planner-rdf ;; documentation included. ;; The .rdf file contains Dublin Core metadata about the source file, the HTML ;; file, and the OWL file produced. It is mainly used to provide information ;; about the relation of the different page versions to various tools. ;; Please note: Currently the .rdf/.owl files are meant for local processing, ;; not Internet publishing. Therefore they contain file-URIs pointing to the ;; local file system. ;; Tested with GNU Emacs 21.3.50... ;; Customisation ;; By default the RDF files are stored in the ;; planner-publishing-directory. For a different location change variable ;; planner-rdf-directory. (eval-when-compile (require 'cl)) (require 'planner) (defvar planner-rdf-version "0.1" "Module Version") (defvar planner-rdf-directory planner-publishing-directory "Directory where the RDF files are stored. Defaults to planner-publishing-directory.") (defvar planner-rdf-schema-planner "http://www.rainervolz.de/schema/2004/11/planner-rdf#" "The Planner schema.") (defvar planner-rdf-base "http://localhost/planner/" "The base URI for Planner info") (defvar planner-rdf-task-prefix (concat planner-rdf-base "task-")) (defvar planner-rdf-note-prefix (concat planner-rdf-base "note-")) (defvar planner-rdf-tag-prefix (concat planner-rdf-base "tag-")) (defvar planner-rdf-link-prefix (concat planner-rdf-base "link-")) (defvar planner-rdf-page-prefix (concat planner-rdf-base "page-")) (defvar planner-rdf-pagetype-prefix (concat planner-rdf-base "page-type-")) (defvar planner-rdf-pagetype-day (concat planner-rdf-base "day-page")) (defvar planner-rdf-pagetype-project (concat planner-rdf-base "topic-page")) (defvar planner-rdf-pagetype-other (concat planner-rdf-base "other-page")) ;; common match strings - tasks (defvar planner-rdf-matchstr-ptaskids "{{Tasks:\\([0-9]+\\)}}" "Finds task ids of the form {{Tasks:}} in Planner tasks.") (defvar planner-rdf-matchstr-ptask "^#\\([A-C]\\)\\([0-9]*\\)\\s-*\\([_oXDCP]\\)\\s-*\\(.+\\)$" "Finds a Planner task in a buffer.") ;; common match strings - notes (defvar planner-rdf-matchstr-pnote "^.#\\([0-9]+\\)\\s-+\\(.+\\)" "Finds the beginning of a Planner note in a buffer. Matches id.") (defvar planner-rdf-matchstr-pnote1 "^\\(.+\\)\\s-+[0-9][0-9]:[0-9][0-9]\\s-+(\\[\\[[0-9]+.[0-9]+.[0-9]+#[0-9]+\\]\\])$" "Note title with time and day page link. Match text.") (defvar planner-rdf-matchstr-pnote2 "^\\(.+\\)\\s-+[0-9][0-9]:[0-9][0-9]\\s-+(\\[\\[.+#[0-9]+\\]\\])$" "Note title with time and project page link. Match text.") (defvar planner-rdf-matchstr-pnote3 "^\\(.+\\)\\s-+[0-9][0-9]:[0-9][0-9]$" "Note title with time, no page link. Match text.") (defvar planner-rdf-matchstr-pnote4 "^.+\\s-+[0-9][0-9]:[0-9][0-9]\\s-+(\\[\\[\\([0-9]+.[0-9]+.[0-9]+#[0-9]+\\)\\]\\])$" "Note title with time and day page link. Match page link.") (defvar planner-rdf-matchstr-pnote5 "^.+\\s-+[0-9][0-9]:[0-9][0-9]\\s-+(\\[\\[\\(.+#[0-9]+\\)\\]\\])$" "Note title with time and project page link. Match page link.") ;; common match strings - links (defvar planner-rdf-matchstr-plink1 "\\[\\[\\([^[\n]+?\\)\\]\\[\\(.+?\\)\\]\\]" "Link like [[][]]. Match link and text.") (defvar planner-rdf-matchstr-plink2 "\\[\\[\\([^[\n]+?\\)\\]\\]" "Link like [[]]. Match link.") (defvar planner-rdf-matchstr-pagenotelink "\\(.+\\)#[0-9]+" "Matches the page part of a page/note reference.") (defvar planner-rdf-matchstr-pagenotelink1 "\\(.+\\)#note[0-9]+" "Matches the page part of a page/note reference.") ;; common match strings - tags (defvar planner-rdf-matchstr-ptag "{{\\(.+?\\)}}" "Tag like {{:}}. Match everything.") ;; hooks (defvar planner-rdf-analysis-note-functions nil "A hook called when the standard note content has been saved. Hook functions must take one parameter, the vector with the note content. Their return value is ignored. Output must be to the current buffer, and in Turtle syntax.") (defvar planner-rdf-analysis-task-functions nil "A hook called when the standard task content has been saved. Hook functions must take one parameter, the vector with the task content. Their return value is ignored. Output must be to the current buffer, and in Turtle syntax.") (defvar planner-rdf-prolog-hook nil "A hook called when the standard turtle file prolog has been saved. Output must be to the current buffer, and in Turtle syntax.") (defvar planner-rdf-epilog-hook nil "A hook called when all standard content has been saved. Output must be to the current buffer, and in Turtle syntax.") (defun planner-rdf-curtz () "Return a string representation of the current time zone." (let* ((tz (current-time-zone)) (secs (car tz)) (mins (/ (abs secs) 60)) (tzstr "") (hours (/ mins 60)) (rmins (% mins 60))) (if (< secs 0) (setq tzstr "-") (setq tzstr "+")) (format "%s%02d:%02d" tzstr hours rmins))) (defun planner-rdf-replace-sth (input replace with) "Replace with in ." (let ((input2 input) (start 0)) (while (not (null (string-match (regexp-opt (list replace)) input2 start))) (setq input2 (replace-match with t t input2)) (setq start (match-end 0))) input2)) (defun planner-rdf-get-taskid (taskdesc) "Retrieve or generate a task id from the description." (if (string-match planner-rdf-matchstr-ptaskids taskdesc) (planner-match-string-no-properties 1 taskdesc) (concat "-" (number-to-string(abs (sxhash taskdesc)))))) (defun planner-rdf-get-task-info () "Retrieve the task information from the current buffer." (let ((results '())) (goto-char (point-min)) (while (not (eobp)) (when (looking-at planner-rdf-matchstr-ptask) (let ((info (planner-task-info-from-string (buffer-name) (match-string 0)))) (add-to-list 'results (vector (buffer-name) (planner-task-priority info) (planner-task-status info) (planner-task-date info) (planner-task-plan info) (planner-task-description info) (planner-task-number info) (planner-rdf-get-taskid (planner-task-description info)) )))) (forward-line)) results)) (defun planner-rdf-get-note-info () "Retrieve the note information from the current buffer." (interactive) (let ((results '())(in-notes 'nil) (curr-note-id 0) (curr-note-headline "") (curr-note-txt "")) (goto-char (point-min)) (while (not (eobp)) (if (looking-at planner-rdf-matchstr-pnote) (progn (if (null in-notes) (setq in-notes 't) (progn ; save previous note (add-to-list 'results (vector (buffer-name) curr-note-id curr-note-headline curr-note-txt)) ;; (planner-rdf-log (concat "Note " curr-note-id " " curr-note-headline)) (setq curr-note-txt "") (setq curr-note-id 0))) (setq curr-note-id (planner-match-string-no-properties 1)) (setq curr-note-headline (planner-match-string-no-properties 2)) ;; zur nächsten - sonst wird der Titel als Text mitgenommen (forward-line))) (if in-notes (setq curr-note-txt (concat curr-note-txt (thing-at-point 'line)))) (forward-line)) ; save the last note if there (if (and in-notes (> (string-to-number curr-note-id) 0)) (progn (add-to-list 'results (vector (buffer-name) curr-note-id curr-note-headline curr-note-txt)) ;; (planner-rdf-log (concat "Note " curr-note-id " " curr-note-headline)) )) results)) (defun planner-rdf-insert-prolog () "Insert a file prolog, necessary schema references etc. Runs the hook planner-rdf-prolog-hook at the end to allow custom content." (insert "\n") (run-hooks 'planner-rdf-prolog-hook)) (defun planner-rdf-insert-dcprolog () "Insert a file prolog, necessary schema references etc." (insert (concat "\n")) (defun planner-rdf-insert-epilog () "Insert a file epilog. Runs the hook planner-rdf-epilog-hook at the end to allow custom content." (run-hooks 'planner-rdf-epilog-hook) (insert "\n")) (defun planner-rdf-retrieve-links (id ctr input parent) "Collect Planner-style links, [[link][text]] or [...]." (let ((start 0)(results '())) (while (not (null (string-match planner-rdf-matchstr-plink1 input start))) (push (list (match-string 1 input) (match-string 2 input) (concat id "-" (number-to-string ctr)) parent) results) (setq ctr (incf ctr)) (setq start (match-end 0))) (setq start 0) (while (not (null (string-match planner-rdf-matchstr-plink2 input start))) (push (list (match-string 1 input) nil (concat id "-" (number-to-string ctr)) parent) results) (setq ctr (incf ctr)) (setq start (match-end 0))) results)) (defun planner-rdf-retrieve-tags (id ctr input parent) "Collect Planner-style tags, {{text:id}}." (let ((start 0)(results '())) (while (not (null (string-match planner-rdf-matchstr-ptag input start))) (push (list (match-string 1 input) (concat id "-" (number-to-string ctr)) parent) results) (setq ctr (incf ctr)) (setq start (match-end 0))) results)) (defun planner-rdf-replace-links (input) "replace Planner-style links, [[link][text]] or [...], with text." (while (not (null (string-match planner-rdf-matchstr-plink1 input 0))) (setq input (replace-match (planner-match-string-no-properties 2 input) t t input))) (while (not (null (string-match planner-rdf-matchstr-plink2 input 0))) (setq input (replace-match "*link*" t t input))) input) (defun planner-rdf-link-type (uri) "Retrieve the link protocol." (if (string-match "\\(\\w+\\):.+" uri) (match-string 1 uri) "unknown")) (defun planner-rdf-tag-id (tag) "Retrieve the id part of a tag." (if (string-match "\\w+:\\(.+\\)" tag) (match-string 1 tag) "unknown")) (defun planner-rdf-escape-uri (uri) "Apply various escapes to the URI." (let* ((uri2 (planner-rdf-replace-sth uri "<" "\\u003c")) (uri3 (planner-rdf-replace-sth uri2 ">" "\\u003e")) (uri4 (planner-rdf-replace-sth uri3 "&" "&"))) uri4)) (defun planner-rdf-escape-string (input) "Apply various escapes to strings." (let* ((input2 (planner-rdf-replace-sth input "\"" "\\u0022")) (input3 (planner-rdf-replace-sth input2 "&" "&")) (input4 (planner-rdf-replace-sth input3 "<" "<")) (input5 (planner-rdf-replace-sth input4 ">" ">")) ) input5)) (defun planner-rdf-print-link (link) "Output a RDF representation of a link. If the link has no name, insert the defined unknown string." (let ((lt (planner-rdf-link-type (elt link 0))) (uri (elt link 0))) (insert "\n") (if (not (null (elt link 1))) (insert "\t" (planner-rdf-escape-string(elt link 1)) "\n") (insert "\t" (planner-rdf-escape-string (if (string= lt "unknown") (substring uri 0 10) (substring uri (+ (length lt) 3) 10))) "\n")) (insert "\t" lt "\n") (insert "\t"(planner-rdf-escape-uri uri) "\n") (insert "\n"))) (defun planner-rdf-print-link2 (link) "Output a resource statement for a link." (insert "\t\n")) (defun planner-rdf-print-tag (tag) "Output a RDF representation of a tag." (insert "\n") (insert "\t" (planner-rdf-link-type (elt tag 0)) "\n") (insert "\t" (planner-rdf-escape-uri(planner-rdf-tag-id (elt tag 0))) "\n") (insert "\n")) (defun planner-rdf-print-tag2 (tag) "Output a resource statement for a tag." (insert "\t\n")) (defun planner-rdf-task-get-nice-description (input) "Extract a nice, readable description. Remove the task ids e.g., {{Tasks:XX}}." (let ((pos (string-match planner-rdf-matchstr-ptaskids input)) (title "")) (when (numberp pos) (setq input (substring input 0 (decf pos)))) (setq title (planner-rdf-replace-links input)) (planner-rdf-replace-sth title "" "") )) (defun planner-rdf-task (taskvector) "Transform task information to turtle syntax. Run the hook 'planner-rdf-task-functions' at the end of the standard output to provide customised content." ;; Generate a task-id (let ((task-id) (task-unique-id) (linkes '()) (tags '())) (setq task-id (elt taskvector 7)) ;; (setq task-unique-id (concat (elt taskvector 0) "-" task-id)) ;; (setq task-unique-id (concat ;; (elt taskvector 0) ;; "#" ;; (elt taskvector 1) ;; (elt taskvector 6))) (setq task-unique-id (concat (elt taskvector 0) "-" task-id)) (setq linkes (planner-rdf-retrieve-links task-unique-id 0 (elt taskvector 5) (concat planner-rdf-task-prefix task-unique-id))) (mapcar 'planner-rdf-print-link linkes) (setq tags (planner-rdf-retrieve-tags task-unique-id 0 (elt taskvector 5) (concat planner-rdf-task-prefix task-unique-id))) (mapcar 'planner-rdf-print-tag tags) (insert "\n") (insert "\t" (elt taskvector 1) "\n") (insert "\t" (elt taskvector 6) "\n") (insert "\t" (elt taskvector 2) "\n") (insert "\t" (planner-rdf-replace-sth (elt taskvector 3) "." "-") "\n") (if (not (null (elt taskvector 4))) (insert "\t\n")) (insert "\t" (planner-rdf-escape-string (planner-rdf-task-get-nice-description (elt taskvector 5))) "\n") ;; if the task-id is negative, it is generated, not good for linking (when (> (string-to-number task-id) -1) (insert "\t" task-id "\n")) (mapcar 'planner-rdf-print-link2 linkes) (mapcar 'planner-rdf-print-tag2 tags) (run-hook-with-args 'planner-rdf-analysis-task-functions taskvector) (insert "\n"))) (defun planner-rdf-note-get-nice-description (input) "Extract a nice description, text only if possible." (let ((title "")) (cond ;; title with time and day page link ((string-match planner-rdf-matchstr-pnote1 input) (setq title (planner-rdf-escape-string(planner-match-string-no-properties 1 input)))) ;; title with time and project page link ((string-match planner-rdf-matchstr-pnote2 input) (setq title (planner-rdf-escape-string(planner-match-string-no-properties 1 input)))) ;; title with time, no page link ((string-match planner-rdf-matchstr-pnote3 input) (setq title (planner-rdf-escape-string (planner-match-string-no-properties 1 input)))) ;; ok, take evrything (t (setq title (planner-rdf-escape-string input)))) (setq title (planner-rdf-replace-links title)) (planner-rdf-replace-sth title "" "") )) (defun planner-rdf-note-get-alias (input) "Extract the alias page link from title string." (let ((alias "")) (cond ;; title with time and day page link ((string-match planner-rdf-matchstr-pnote4 input) (setq alias (planner-rdf-escape-string(planner-match-string-no-properties 1 input)))) ;; title with time and project page link ((string-match planner-rdf-matchstr-pnote5 input) (setq alias (planner-rdf-escape-string(planner-match-string-no-properties 1 input)))) ;; ok, nothing there (t (setq alias ""))) (planner-rdf-replace-sth alias "#" "-"))) (defun planner-rdf-note-get-plan (page input) "Extract the alias page link from title string." (let ((plan "") (alias (planner-rdf-note-get-alias input))) (cond ;; there is something ((string-match planner-rdf-matchstr-pagenotelink alias) (setq plan (planner-rdf-escape-string(planner-match-string-no-properties 1 alias)))) ((string-match planner-rdf-matchstr-pagenotelink1 alias) (setq plan (planner-rdf-escape-string(planner-match-string-no-properties 1 alias)))) ;; ok, nothing there (t (setq plan page))) plan)) (defun planner-rdf-note (notevector) "Transform note information to RDF. Run the hook 'planner-rdf-note-functions' at the end of the standard output to provide customised content." ;; Generate a note-id (let ((note-id (concat (elt notevector 0) "-" (elt notevector 1))) (title (planner-rdf-note-get-nice-description (elt notevector 2))) (alias (planner-rdf-note-get-alias (elt notevector 2))) (linksall '()) (tagsall '())) ;; links from title and body (let* ((linkst (planner-rdf-retrieve-links note-id 0 title (concat planner-rdf-note-prefix note-id))) (linksb (planner-rdf-retrieve-links note-id (length linkst) (elt notevector 3) (concat planner-rdf-note-prefix note-id)))) (setq linksall (append linkst linksb)) (mapcar 'planner-rdf-print-link linksall)) (let* ((tagst (planner-rdf-retrieve-tags note-id 0 title (concat planner-rdf-note-prefix note-id))) (tagsb (planner-rdf-retrieve-tags note-id (length tagst) (elt notevector 3) (concat planner-rdf-note-prefix note-id)))) (setq tagsall (append tagst tagsb)) (mapcar 'planner-rdf-print-tag tagsall)) (insert "\n") (insert "\t" note-id "\n") ; find a date - first try buffer name (if (string-match "^\\([0-9]+.[0-9]+.[0-9]+\\)$" (elt notevector 0)) (insert "\t" (planner-rdf-replace-sth (elt notevector 0) "." "-") "\n") (progn ; no luck, try title line (if (string-match "(\\[\\[\\([0-9]+.[0-9]+.[0-9]+\\)#[0-9]+\\]\\])" (elt notevector 2)) (insert "\t" (planner-rdf-replace-sth (planner-match-string-no-properties 1 (elt notevector 2)) "." "-") "\n")))) ;; find time (if (string-match "\\s-+\\([0-9][0-9]:[0-9][0-9]\\)\\s-+\\|\\s-+\\([0-9][0-9]:[0-9][0-9]\\)$" (elt notevector 2)) (insert "\t" (if (planner-match-string-no-properties 1 (elt notevector 2)) (planner-match-string-no-properties 1 (elt notevector 2)) (planner-match-string-no-properties 2 (elt notevector 2))) ":00\n")) (insert "\t" title "\n") (when (not (string= "" alias)) (insert "\t\n")) (mapcar 'planner-rdf-print-link2 linksall) (mapcar 'planner-rdf-print-tag2 tagsall) (run-hook-with-args 'planner-rdf-analysis-note2turtle-functions notevector) (insert "\n"))) (defun planner-rdf-insert-page-info (name tasks notes) "Create a page object." (insert "\n") (let ((type (if (string-match "^[0-9]\\{4\\}[\\.\\-][0-9]\\{2\\}[\\.\\-][0-9]\\{2\\}" name) planner-rdf-pagetype-day planner-rdf-pagetype-project))) (insert "\t\n") ) (mapcar (lambda (task) (insert "\t\n")) tasks) (mapcar (lambda (note) (insert "\t\n")) notes) (insert "\n")) (defun planner-rdf-metadata (file) "Create Dublin Core metadata for the varous files involved." ;; The source file (let ((name (file-name-nondirectory file)) (rdfdir (file-name-as-directory planner-rdf-directory))) (insert "\n") (insert "\t" (file-name-nondirectory file) "\n") (insert "\t" planner-rdf-base "page-" name "\n") (insert "\ttext\n") (if (string-match "^[0-9]\\{4\\}[\\.\\-][0-9]\\{2\\}[\\.\\-][0-9]\\{2\\}" name) (progn (insert "\t" planner-rdf-pagetype-day "\n") (insert "\t" planner-rdf-base "date/" (planner-rdf-replace-sth name "." "-") "\n")) (progn (insert "\t" planner-rdf-pagetype-project "\n") (insert "\t" planner-rdf-base "topic/" name "\n"))) (insert "\n") ;; The HTML file (insert "\n") (insert "\t" name "\n") (insert "\tfile:" file "\n") (insert "\ttext/html\n") (insert "\n") ;; The OWL file (insert "\n") (insert "\t" name "\n") (insert "\tfile:" file "\n") (insert "\tapplication/rdf+xml\n") (insert "\n") ) ) ;;;###autoload (defun planner-rdf-publish-file (file) "Publish the file in RDF format, if called by PlannerMode. Designed to be called via `muse-after-publish-hook'. Non-Planner files, matching `muse-image-regexp' will be treated differently. Currently they are simply ignored." (interactive "f") (when (eq major-mode 'planner-mode) (if (string-match muse-image-regexp file) (message (concat "planner-rdf: Ignored file " file)) (let ((tasks nil) (notes nil)) (let ((mybuff (get-file-buffer file)) (opened nil)) (when (not mybuff) (setq mybuff (find-file file)) (setq opened t)) (with-current-buffer mybuff (setq tasks (planner-rdf-get-task-info))) (with-current-buffer mybuff (setq notes (planner-rdf-get-note-info))) (if (and (not (buffer-modified-p mybuff)) opened) (kill-buffer mybuff))) (let ((mybuff2 (find-file (expand-file-name (concat (file-name-as-directory planner-rdf-directory) (file-name-nondirectory file) ".owl"))))) (with-current-buffer mybuff2 (erase-buffer) (planner-rdf-insert-prolog) (mapcar 'planner-rdf-task tasks) (mapcar 'planner-rdf-note notes) (planner-rdf-insert-page-info (file-name-nondirectory file) tasks notes) (planner-rdf-insert-epilog) (let ((backup-inhibited t)) (save-buffer))) (kill-buffer mybuff2)) (let ((mybuff3 (find-file (expand-file-name (concat (file-name-as-directory planner-rdf-directory) (file-name-nondirectory file) ".rdf"))))) (with-current-buffer mybuff3 (erase-buffer) (planner-rdf-insert-dcprolog) (planner-rdf-metadata file) (planner-rdf-insert-epilog) (let ((backup-inhibited t)) (save-buffer))) (kill-buffer mybuff3)) )))) ;;;###autoload (defun planner-rdf-publish-index () "Create an index for the .rdf files. Will be called via `muse-after-publish-hook'. Creates index.rdf, a rdf:bag, with all existing .rdf files as items." (interactive) (let ((rdf-index (expand-file-name (concat (file-name-as-directory planner-rdf-directory) "index.rdf")))) (when (file-exists-p rdf-index) (delete-file rdf-index)) (with-temp-buffer (erase-buffer) (message "Creating RDF index...") (insert "\n") (insert "\n") (insert "\t\n") (let ((rdf-files (directory-files (file-name-as-directory planner-rdf-directory) t "\\.rdf$" nil))) (insert (mapconcat (lambda (name) (concat "\t\t")) rdf-files "\n"))) (insert "\n\t\n") (insert "\n") (let ((backup-inhibited t)) (write-file rdf-index nil))))) (provide 'planner-rdf) planner-el/planner-rdf.owl000066400000000000000000000427741226462314700160730ustar00rootroot00000000000000 OWL schema for Emacs PlannerMode. $Id$ Represents a PlannerMode link, e.g. [[http://www.emacswiki.org][EmacsWiki]]). Abstract superclass for PlannerMode-related concepts. A representation of PlanerMode note. Contains all data except the note text. However, all tags and links mentioned in the note text are stored in the link/tag collections. A represetation of tags i.e., {{<tag-id>:<tag-value>}}. An example are the global task numbers: {{Tasks:153}}. Tags are used to represent abstract things, for which there is no link address. Represetation of a PlannerMode task. Contains all information. Tags and links mentioned are stored in their collections. Links to the contained notes Links to contained tasks The same element on a different page A collection of PlannerMode links mentioned in the element. The collection PlannerTags entioned in the element. The value of the {{Tasks:<Number>}} tag, if used. PlannerMode uses currently 3 values (A,B,C) to indicate the importance of a task. C B A Type means the URI scheme e.g., http, mailto etc. A convenience field for searching. If the note title contains a time (HH:MM) it is stored here. Name of the plan page. The link's label. Optional. A number indicating the number of a task relative to the task-priority. _ P o C D X PlannerMode currently indicates the status of a task with "_" not started, "P" pending, "o" ongoing, "X" finished, "C" cancelled, and "D" delegated. File URI,containing the task. The note title, as plain text. The ID (number) of the note, relative to the containing page. The complet URI of the link. A page about a certain topic or project. A journal page about a day in the life of ... No day or topic page, probably a generated page, an index etc. planner-el/planner-registry.el000066400000000000000000000313171226462314700167560ustar00rootroot00000000000000;;; planner-registry.el --- registry for Planner ;; Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Time-stamp: <2006-01-23 18:21:18 guerry> ;; ;; Author: Bastien Guerry ;; Version: $Id: planner-registry.el,v 0.1 2006/01/23 17:21:21 guerry Exp $ ;; Keywords: planner muse registry ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your ;; option) any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This module provides a way to keep track of all the URLs in your ;; projects, and to list them depending on the current buffer. The ;; URLs are defined in `muse-url-protocols' - it does NOT include ;; wikiwords (for now). ;; ;; If a URL has been created by `planner-create-task-from-buffer', ;; going to that buffer and calling `planner-registry-show' will show you ;; where planner put the URL. ;; ;; Say for example that you created a task from an e-mail. Go to that ;; e-mail and call `planner-registry-show': it will open a new buffer ;; displaying the files (in a muse links format) where a link to this ;; e-mail has been added. ;;; Getting Started: ;; Put this in your init file: ;; ;; (require 'planner-registry) ;; (planner-registry-initialize) ;; ;; You MUST put it after the place where where Planner has been loaded ;; in your configuration file. ;; ;; If you want the registry to be updated each time you save a Planner ;; file, add this: ;; ;; (planner-registry-insinuate) ;; ;; If you don't want to update the registry each time a file is ;; written, you can do it manually with `planner-registry-update': it ;; will update the registry for saved muse/planner buffers only. ;; ;; There's no default `define-key' for `planner-registry-show' because ;; it's not bounded to one particular mode. You can bound it to ;; whatever you want. ;;; Todo: ;; 1) Better windows manipulations ;; 2) Wiki links support ;;; Problems: ;; If you're using this with Planner, the default value of ;; `planner-bibtex-separator' must be changed from ":" to something ;; else. ;; ;; (setq planner-bibtex-separator "#") ;; ;; "#" as a separator enables you to perform fuzzy-matching on bibtex ;; URLs as well. ;;; History: ;; 2005.11.22 - new release. ;; 2005.11.18 - first release. ;;; Contributors: ;;; Code: ;;;_* Prerequisites (require 'planner) ;;;_* Options (defgroup planner-registry nil "A registry for Planner." :prefix "planner-registry-" :group 'muse) ;; You can setq this var to what do you like. (defcustom planner-registry-file (concat (getenv "HOME") "/.planner-registry.el") "The registry file." :type 'string :group 'planner-registry) (defcustom planner-registry-min-keyword-size 3 "Minimum size for keywords." :type 'integer :group 'planner-registry) (defcustom planner-registry-max-keyword-size 10 "Maximum size for keywords." :type 'integer :group 'planner-registry) (defcustom planner-registry-max-number-of-keywords 3 "Maximum number of keywords." :type 'integer :group 'planner-registry) (defcustom planner-registry-ignore-keywords '("E-Mail" "from" "www") "A list of ignored keywords." :type 'list :group 'planner-registry) (defcustom planner-registry-show-level 0 "Level for `planner-registry-show'. 0 means that this function shows only exact matches. 1 means that this function also shows descriptive matches. 2 (or more) means that this function also shows fuzzy matches." :type 'boolean :group 'planner-registry) ;;;_* Other variables and constants (defvar planner-registry-alist nil "An alist containing the Planner registry.") (defconst planner-registry-url-regexp (concat "\\(" (mapconcat 'car muse-url-protocols "\\|") "\\)" "[^][" muse-regexp-blank "\"'()^`{}\n]*[^][" muse-regexp-blank "\"'()^`{}.,;\n]+") "A regexp that matches Muse URL links.") (defconst planner-registry-link-regexp (concat "\\[\\[\\(" planner-registry-url-regexp "\\)\\]\\[\\([^][\n]+\\)\\]\\]") "A regexp that matches Muse explicit links.") (defconst planner-registry-url-or-link-regexp (concat "\\(" planner-registry-url-regexp "\\)\\|" planner-registry-link-regexp) "A regexp that matches both Muse URL and explicit links. The link is returned by `match-string' 3 or 1. The protocol is returned bu `match-string' 4 or 2. The description is returned by `match-string' 5") ;;;_* Core code ;;;###autoload (defun planner-registry-initialize (&optional from-scratch) "Set `planner-registry-alist' from `planner-registry-file'. If `planner-registry-file' doesn't exist, create it. If FROM-SCRATCH is non-nil, make the registry from scratch." (interactive "P") (if (or (not (file-exists-p planner-registry-file)) from-scratch) (planner-registry-make-new-registry) (planner-registry-read-registry)) (message "Planner registry initialized")) (defun planner-registry-update nil "Update the registry from the current buffer." (interactive) (let* ((from-file (buffer-file-name)) (new-entries (planner-registry-new-entries from-file))) (planner-registry-update-registry from-file new-entries)) (with-temp-buffer (insert-file-contents planner-registry-file) (eval-buffer))) (defun planner-registry-insinuate nil "Call `planner-registry-update' after saving in Planner mode. Use with caution. This could slow down things a bit." (interactive) (add-hook 'planner-mode-hook (lambda nil (add-hook 'after-save-hook 'planner-registry-update t t)))) (defun planner-registry-show (&optional level) "Show entries at LEVEL. See `planner-registry-show-level' for details." (interactive "p") (let ((annot (run-hook-with-args-until-success 'planner-annotation-functions)) (level (or level planner-registry-show-level))) (if (not annot) (message "Annotation is not supported for this buffer") (let ((entries (planner-registry-get-entries annot level))) (if (not entries) (message (format "No match (level %d) for \"%s\"" level (progn (string-match planner-registry-url-or-link-regexp annot) (match-string 5 annot)))) (delete-other-windows) (switch-to-buffer-other-window (set-buffer (get-buffer-create "*Planner registry*"))) (erase-buffer) (dolist (elem entries) (dolist (entry elem) (insert entry)) (when elem (insert "\n"))) (muse-mode)))))) (defun planner-registry-create nil "Create `planner-registry-file'." (let ((items planner-registry-alist) item) (with-temp-buffer (find-file planner-registry-file) (erase-buffer) (insert (with-output-to-string (princ ";; -*- emacs-lisp -*-\n") (princ ";; Planner registry\n;; What are you doing here?\n\n") (princ "(setq planner-registry-alist\n'(\n") (while items (when (setq item (pop items)) (prin1 item) (princ "\n"))) (princ "))\n"))) (save-buffer) (kill-buffer (current-buffer)))) (message "Planner registry created")) (defun planner-registry-entry-output (entry) "Make an output string for ENTRY." (concat " - [[pos://" (car entry) "#" (nth 1 entry) "][" (planner-registry-get-project-name (car entry)) ": " (file-name-nondirectory (car entry)) "]] - [[" (nth 2 entry) "][" (nth 3 entry) "]]\n")) (defun planner-registry-get-project-name (file) "Get project name for FILE." (let ((file1 (directory-file-name (file-name-directory file)))) (planner-replace-regexp-in-string "/?[^/]+/" "" file1 t t))) (defun planner-registry-read-registry nil "Set `planner-registry-alist' from `planner-registry-file'." (with-temp-buffer (find-file planner-registry-file) (eval-buffer) (kill-buffer (current-buffer)))) (defun planner-registry-update-registry (from-file new-entries) "Update the registry FROM-FILE with NEW-ENTRIES." (with-temp-buffer (find-file planner-registry-file) (goto-char (point-min)) (while (re-search-forward (concat "^(\"" from-file) nil t) (delete-region (planner-line-beginning-position) (planner-line-end-position))) (goto-char (point-min)) (re-search-forward "^(\"" nil t) (goto-char (match-beginning 0)) (dolist (elem new-entries) (insert (with-output-to-string (prin1 elem)) "\n")) (save-buffer) (kill-buffer (current-buffer))) (message (format "Planner registry updated for URLs in %s" (file-name-nondirectory (buffer-file-name))))) (defun planner-registry-make-new-registry nil "Make a new `planner-registry-alist' from scratch." (setq planner-registry-alist nil) (let ((muse-directories (mapcar 'caadr muse-project-alist)) muse-directory) (while muse-directories (when (setq muse-directory (pop muse-directories)) (mapcar (lambda (file) (unless (or (file-directory-p file) (let ((case-fold-search nil)) (string-match muse-project-ignore-regexp file))) (dolist (elem (planner-registry-new-entries file)) (add-to-list 'planner-registry-alist elem)))) (directory-files muse-directory t))))) (planner-registry-create)) (defun planner-registry-new-entries (file) "List links in FILE that will be put in the registry." (let (result) (with-temp-buffer (insert-file-contents file) (goto-char (point-min)) (while (re-search-forward planner-registry-url-or-link-regexp nil t) (let* ((point (number-to-string (match-beginning 0))) (link (or (match-string-no-properties 3) (match-string-no-properties 1))) (desc (or (match-string-no-properties 5) (progn (string-match planner-registry-url-regexp link) (substring link (length (match-string 1 link)))))) (keywords (planner-registry-get-keywords desc)) (ln-keyword (planner-registry-get-link-keywords link))) (add-to-list 'result (list file point link desc keywords ln-keyword))))) result)) (defun planner-registry-get-entries (annot level) "Show the relevant entries in the registry. ANNOT is the annotation for the current buffer. LEVEL is set interactively or set to `planner-registry-show-level'." (when (string-match planner-registry-url-or-link-regexp annot) (let* ((link (or (match-string 3 annot) (match-string 1 annot))) (desc (or (match-string 5 annot) "")) exact-match descriptive fuzzy) (dolist (entry planner-registry-alist) (let* ((output (planner-registry-entry-output entry)) (keyword (nth 4 entry)) (ln-keyword (nth 5 entry))) ;; exact matching (when (equal (nth 2 entry) link) (add-to-list 'exact-match output)) ;; descriptive matching (when (and (> level 0) (equal (nth 3 entry) desc)) (unless (member output exact-match) (add-to-list 'descriptive output))) ;; fuzzy matching (when (and (> level 1) (or (string-match ln-keyword link) (string-match keyword desc))) ;; use (planner-registry-get-keywords)? (unless (or (member output exact-match) (member output descriptive)) (add-to-list 'fuzzy output))))) (when exact-match (add-to-list 'exact-match (concat "* Exact match(es):\n\n"))) (when descriptive (add-to-list 'descriptive (concat "* Description match(es):\n\n"))) (when fuzzy (add-to-list 'fuzzy (concat "* Fuzzy match(es):\n\n"))) (cond (fuzzy (list exact-match descriptive fuzzy)) (descriptive (list exact-match descriptive)) (exact-match (list exact-match)) (t nil))))) (defun planner-registry-get-link-keywords (link) "Make a list of keywords for LINK." (setq link (car (planner-split-string link "#" t)))) (defun planner-registry-get-keywords (desc) "Make a list of keywords for DESC." (let ((kw (planner-split-string desc "[ ./]+" t))) (mapcar (lambda (wd) (setq kw (delete wd kw))) planner-registry-ignore-keywords) (setq kw (mapcar (lambda (a) (when (>= (length a) planner-registry-min-keyword-size) (substring a 0 (if (> (length a) planner-registry-max-keyword-size) planner-registry-max-keyword-size (length a))))) kw)) (setq kw (delq nil kw)) (setq kw (nthcdr (- (length kw) planner-registry-max-number-of-keywords) kw)) (mapconcat (lambda (e) e) kw ".*"))) (provide 'planner-registry) ;;; planner-registry.el ends here ;; ;; Local Variables: ;; indent-tabs-mode: t ;; tab-width: 8 ;; End: planner-el/planner-report.el000066400000000000000000000255611226462314700164250ustar00rootroot00000000000000;;; planner-report.el --- create a timely status report based on planner pages ;; Copyright (C) 2004, 2006, 2008 Andrew J. Korty ;; Parts copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Filename: planner-report.el ;; Version: $Revision: 1.11 $ ;; Keywords: hypermedia ;; Author: Andrew J. Korty ;; Maintainer: Andrew J. Korty ;; Description: Create a timely status report based on planner pages ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This library creates a status report for a given timespan. The ;; report itself is just another Planner page in your planner ;; directory. Once generated, it contains tasks and notes culled from ;; active project pages. Tasks are only shown if they are incomplete ;; or were completed within the timespan. Notes are shown if they ;; were created during the timespan. Tasks and notes are grouped ;; together under a heading for their corresponding project. ;; The idea is you have one of these status reports generated ;; periodically (say, every couple of weeks). Perhaps you use cron to ;; run them automatically and then mail you a reminder that they've ;; been done. Then you can edit the page, adding verbiage where it is ;; needed and removing irrelevant items. This editing process is as ;; easy as editing any other Planner page. Finally, you can publish ;; the page along with the rest of your planner using M-x ;; muse-project-publish. ;; If you use planner-authz.el, you can tell planner-report.el only to ;; consult project pages that a given list of users ;; (planner-report-authz) can access when generating the report. For ;; example, if you're preparing a status report for your boss, add ;; yourself and him to planner-report-authz. The resulting status ;; report will only contain information the two of you are supposed to ;; have access to, and the report itself will be similarly restricted. ;; * Startup and Usage ;; Once this file is installed, add the following to your .emacs file: ;; (require 'planner-report) ;; Then you can use the following command to generate a status report: ;; M-x planner-report-generate ;; You will be prompted for a beginning and ending date, and then the ;; status report will be generated. You can then edit it to your ;; liking and publish it just like you would the rest of your planner. ;; * Customization ;; All user-serviceable options can be customized with ;; M-x customize-group RET planner-report RET. ;; * Contributors ;; Seth Falcon (sethfalcon AT gmail DOT com) helped port this to ;; Planner-Muse. ;; Yann Hodique helped port this to Muse. ;; $Id: planner-report.el,v 1.11 2004/12/06 02:39:00 ajk Exp $ ;;; Code: (require 'muse) (require 'planner) (defgroup planner-report nil "A planner.el extension for generating timely status reports based on planner pages." :group 'planner :prefix "planner-report") (defcustom planner-report-authz nil "List of users a status report should be restricted to. When status reports are generated, only planner pages accessible by these users will be consulted, and the resulting status report will be similarly restricted." :group 'planner-report :type '(repeat string)) (defcustom planner-report-pretty-print-plan-pages t "If non-nil, pretty print plan pages. If nil, leave page names as-is. This requires muse-wiki.el to work properly." :group 'planner-report :type 'boolean) (defcustom planner-report-remove-task-numbers t "Remove task numbers when generating status reports." :group 'planner-report :type 'boolean) (defcustom planner-report-replace-note-numbers "**" "If non-nil, a string with which to replace note numbers when generating status reports." :group 'planner-report :type 'string) (defcustom planner-report-unfinished-offset nil "If non-nil, the offset in days from the current date of unfinished tasks to include in the status report. If nil, include all unfinished tasks." :group 'planner-report :type '(choice (integer :tag "Number of days") (const :tag "Include all unifinished tasks" nil))) (defvar planner-report-version "$Revision: 1.11 $" "Version of of planner-report.el.") ;;;###autoload (defun planner-report-generate (begin end) "Generate a status report spanning a period from BEGIN to END. BEGIN and END are in the format YYYY.MM.DD." (interactive (let ((planner-expand-name-favor-future-p (or planner-expand-name-favor-future-p planner-task-dates-favor-future-p))) (list (planner-read-date "Start date") (planner-read-date "End date")))) (save-some-buffers nil (lambda () (planner-derived-mode-p 'planner-mode))) (cd (planner-directory)) (let ((filename (concat "StatusReport" end))) (when (and muse-file-extension (not (string= muse-file-extension ""))) (setq filename (concat filename "." muse-file-extension))) (with-temp-buffer (when planner-report-authz (require 'planner-authz) (insert "#authz " (mapconcat 'identity planner-report-authz " ") "\n")) (insert "#title Status report for " begin " to " end "\n") (let* ((unsorted-pages (if planner-report-authz (planner-authz-file-alist planner-report-authz) (planner-file-alist))) (pages (sort unsorted-pages (lambda (a b) (string< (car a) (car b))))) notes tasks) (while pages (when (caar pages) ;; Add only project pages, and skip other status reports (unless (or (string-match "^StatusReport" (caar pages)) (string-match planner-date-regexp (caar pages))) (with-temp-buffer (with-planner (insert-file-contents (cdar pages)) (setq tasks (planner-report-find-tasks (caar pages) begin end)) (setq notes (planner-report-find-notes (caar pages) begin end))))) ;; Insert a linked heading if we found anything (if (or notes tasks) (insert "\n* [[" (caar pages) "][" (if (and planner-report-pretty-print-plan-pages (fboundp 'muse-wiki-publish-pretty-title)) (muse-wiki-publish-pretty-title (caar pages)) (caar pages)) "]]\n\n")) (when tasks (insert tasks "\n\n") (setq tasks nil)) (when notes (insert notes "\n") (setq notes nil))) (setq pages (cdr pages)))) (write-file filename t)) (find-file filename))) (defun planner-report-find-notes (page begin end) "Find notes on PAGE that were created between BEGIN and END. BEGIN and END are formatted as YYYY.MM.DD." (goto-char (point-min)) (let (result) (while (re-search-forward "^\\.#[0-9]+\\s-+" nil t) (let ((note (buffer-substring (planner-line-beginning-position) (save-excursion ;; Find the end of this note (maybe EOF) (re-search-forward "^\\(\\.#[0-9]+\\s-+\\|\\*\\*?\\s-+\\)" nil 1) (goto-char (planner-line-beginning-position)) (point)))) (info (planner-current-note-info))) (when info (let* ((link (planner-note-link info)) (date (if link (planner-link-base link)))) ;; Snarf if note is associated with a date that is in range (and date (not (string< date begin)) (not (string< end date)) (progn (if planner-report-replace-note-numbers (setq note (planner-replace-regexp-in-string "^\\.#[0-9]+" planner-report-replace-note-numbers note t t))) (setq result (if result (concat note result) note)))))))) result)) (defun planner-report-find-tasks (page begin end) "Find cancelled or completed tasks on PAGE with a date between BEGIN and END and any unfinished tasks with a date constrained by `planner-report-unfinished-offset'. BEGIN and END are formatted as YYYY.MM.DD." (goto-char (point-min)) (let (result) (while (re-search-forward "^#[A-C]" nil t) (let* ((task (buffer-substring (planner-line-beginning-position) (planner-line-end-position))) (info (planner-task-info-from-string page task))) (when info (let ((date (planner-task-date info))) ;; If the task isn't cancelled nor completed and has a ;; date less than or equal to planner-report-unfinished ;; away, snarf. If it has been cancelled or completed and ;; the date is in range, snarf. (and date (or (and (not (or (equal (planner-task-status info) "C") (equal (planner-task-status info) "X"))) (or (null planner-report-unfinished-offset) (not (string< (planner-calculate-date-from-day-offset (planner-date-to-filename (decode-time (current-time))) planner-report-unfinished-offset) date)))) (and (not (string< date begin)) (not (string< end date)))) (progn (if planner-report-remove-task-numbers (setq task (planner-replace-regexp-in-string "^\\(#[A-C]\\)\\([0-9]+ +\\)" "\\1 " task t nil))) (setq result (if result (concat result "\n" task) task)))))))) result)) (provide 'planner-report) ;;; planner-report.el ends here planner-el/planner-rmail.el000066400000000000000000000113411226462314700162050ustar00rootroot00000000000000;;; planner-rmail.el --- RMAIL support for Planner, an organizer for Emacs ;; Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2004, 2008 Frederik Fouvry ;;; Commentary: ;; ;;;_* Commentary ;;;_ + Package description ;; Emacs Lisp Archive Entry ;; Filename: planner-rmail.el ;; Keywords: hypermedia ;; Author: John Wiegley ;; Description: Use Emacs for life planning ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_ + Usage ;; Place planner-rmail.el in your load path and add this to your .emacs: ;; ;; (require 'planner-rmail) ;; ;; RMAIL URLs are of the form ;; ;; rmail://PATH/TO/INBOX/message-id ;; ;; Annotations will be of the form ;; [[rmail://PATH/TO/INBOX/][E-mail from Sacha Chua]] ;;;_ + Contributors ;; Frederik Fouvry (fouvry AT coli DOT uni-sb DOT de) made an ;; improvement to gracefully deal with missing messages. (require 'planner) (require 'rmail) ;;; Code: ;; This isn't provided in XEmacs (defun planner-rmail-narrow-to-non-pruned-header () "Narrow to the whole (original) header of the current message." (if (fboundp 'rmail-narrow-to-non-pruned-header) (rmail-narrow-to-non-pruned-header) (let (start end) (narrow-to-region (rmail-msgbeg rmail-current-message) (point-max)) (goto-char (point-min)) (forward-line 1) (if (= (following-char) ?1) (progn (forward-line 1) (setq start (point)) (search-forward "*** EOOH ***\n") (setq end (match-beginning 0))) (forward-line 2) (setq start (point)) (search-forward "\n\n") (setq end (1- (point)))) (narrow-to-region start end) (goto-char start)))) ;;;###autoload (defun planner-rmail-annotation-from-mail () "Return an annotation for the current message. This function can be added to `planner-annotation-functions'." (when (eq major-mode 'rmail-mode) (save-excursion (save-restriction (planner-rmail-narrow-to-non-pruned-header) (planner-make-link (concat "rmail://" (buffer-file-name) "/" (mail-fetch-field "message-id")) (if (and planner-ignored-from-addresses (string-match planner-ignored-from-addresses (mail-fetch-field "from"))) (concat "E-mail to " (planner-get-name-from-address (mail-fetch-field "to"))) (concat "E-mail from " (planner-get-name-from-address (mail-fetch-field "from")))) t))))) ;;;###autoload (defun planner-rmail-browse-url (url) "If this is an RMAIL URL, jump to it." (when (string-match "\\`rmail://\\(.+\\)/\\(.+?\\)$" url) (let ((message-id (match-string 2 url)) (file (match-string 1 url)) message-number) ;; Backward compatibility (save-excursion (save-window-excursion (rmail (if (string= file "RMAIL") rmail-file-name file)) (setq message-number (save-restriction (widen) (goto-char (point-max)) (if (re-search-backward (concat "^Message-ID:\\s-+" (regexp-quote message-id)) nil t) (rmail-what-message)))))) (if message-number (progn (rmail (if (string= file "RMAIL") rmail-file-name file)) (rmail-show-message message-number) message-number) (error "Message not found"))))) (planner-add-protocol "rmail://" 'planner-rmail-browse-url nil) (add-hook 'planner-annotation-functions 'planner-rmail-annotation-from-mail) (custom-add-option 'planner-annotation-functions 'planner-rmail-annotation-from-rmail) (planner-update-wiki-project) (provide 'planner-rmail) ;;;_* Local emacs vars. ;; Local variables: ;; allout-layout: (* 0 : ) ;; End: ;;; planner-rmail.el ends here planner-el/planner-rss.el000066400000000000000000000247741226462314700157260ustar00rootroot00000000000000;;; planner-rss.el --- RSS export for the Emacs Planner (planner.el) ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 David D. Smith ;; Emacs Lisp Archive Entry ;; Filename: planner-rss.el ;; Keywords: hypermedia ;; Author: Sacha Chua ;; Description: Export planner entries as an RSS feed ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; If you use `remember-to-planner' to keep daily notes, you can ;; automatically publish remembered notes as an RSS feed by adding the ;; following code to your .emacs: ;; ;; (add-to-list 'remember-planner-append-hook 'planner-rss-add-note t) ;; ;; You can also invoke `planner-rss-add-note' on any note you would ;; like added. ;;;_ + Contributors ;; David Smith (davidsmith AT acm DOT org) ported this to work with ;; Muse. ;;; Code: (require 'planner) (require 'planner-publish) (defgroup planner-rss nil "Planner options for RSS feeds." :prefix "planner-rss-" :group 'planner) (defcustom planner-rss-base-url "" "Base URL for blog entries. Should include trailing /. Example: http://sacha.free.net.ph/notebook/wiki/" :type 'string :group 'planner-rss) ;; On my system, this is set to ;;'(("." ;; "/home/sacha/public_html/notebook/wiki/blog.rdf" ;; " ;;sachachua's blog ;;http://sacha.free.net.ph/notebook/wiki/today.php ;;Random notes ;;\n")) (defcustom planner-rss-category-feeds nil "List of (CONDITION FILENAME INITIAL-CONTENTS). If CONDITION is a regexp, all entries that match the regexp in either title or body will be included in FILENAME. If CONDITION is a function with one argument, it will be called with the marked-up text, and a non-nil return value means include this entry in FILENAME. If INITIAL-CONTENTS is non-nil, it is used to initialize the file if the file is not found or is corrupted. Example: '((\".\" \"/home/sacha/public_html/notebook/wiki/blog.rdf\" \" sachachua's blog http://sacha.free.net.ph/notebook/wiki/today.php Random notes \n\"))" :type '(repeat (group (choice regexp function) file string)) :group 'planner-rss) (defcustom planner-rss-feed-limits nil "A list of (REGEX SIZE-LIMIT ITEM-LIMIT). REGEX is a regular expression that matches the filename. SIZE-LIMIT, if non-nil, is the upper limit in characters. ITEM-LIMIT, if non-nil, is the upper limit in items. If the feed exceeds the stated limits, older items are deleted." :type '(alist :key-type regexp :value-type (group (choice :tag "Characters: " (const :tag "No limit" nil) (integer)) (choice :tag "Size: " (const :tag "No limit" nil) (integer)))) :group 'planner-rss) ;; Determined from planner-rss-category-feeds. ;; You don't need to set this. (defvar planner-rss-file-name nil "Filename of current RSS feed.") (defvar planner-rss-initial-contents nil "Initial contents.") (defun planner-rss-add-item (item) "Add an item to the top of the items list in `planner-rss-file-name'. It will have TITLE, LINK, DESCRIPTION, PUBDATE and CATEGORIES. `planner-rss-initialize' is called if necessary." (save-excursion (save-window-excursion (find-file planner-rss-file-name) (goto-char (point-min)) (unless (re-search-forward "\\|" nil t) (progn (erase-buffer) (insert planner-rss-initial-contents) (goto-char (point-max)) (re-search-backward ""))) (goto-char (match-beginning 0)) (insert item) (planner-rss-limit) (save-buffer)))) (defun planner-rss-strip-tags (string) "Remove all tags from STRING." (planner-replace-regexp-in-string "<[^>]+>" "" string)) ;;;###autoload (defun planner-rss-add-note (&optional feed) "Export the current note using `planner-rss-add-item'. If FEED is non-nil, add the note to the specified feed only. Call with the interactive prefix in order to be prompted for FEED." (interactive (list (when current-prefix-arg (read-file-name "Feed: ")))) (save-window-excursion (save-excursion (save-restriction (when (planner-narrow-to-note) (let* ((seen) (text (buffer-substring-no-properties (point-min) (point-max))) (muse-publishing-current-file (buffer-file-name)) (entry (with-temp-buffer (insert text) (muse-publish-markup-buffer "*rss*" "planner-rss") (buffer-string)))) (dolist (feed planner-rss-category-feeds nil) (let ((condition (elt feed 0)) (planner-rss-file-name (elt feed 1)) (planner-rss-initial-contents (elt feed 2))) (when (cond ((functionp condition) (funcall condition text)) ((stringp condition) (string-match condition text)) (t condition)) (unless (member planner-rss-file-name seen) (add-to-list 'seen planner-rss-file-name) (planner-rss-add-item entry))))))))))) (defun planner-rss-limit () "Apply limits specified in `planner-rss-feed-limits'." (let ((filename (expand-file-name (planner-current-file)))) (mapcar (lambda (item) (when (string-match (elt item 0) filename) (planner-rss-limit-size (elt item 1)) (planner-rss-limit-items (elt item 2)))) planner-rss-feed-limits))) (defun planner-rss-limit-size (limit) "Delete RSS items that cause this file to go over LIMIT characters." (when limit (widen) (goto-char limit) (unless (eobp) (re-search-backward "" nil t) (let ((start (match-beginning 0))) (re-search-forward "" nil t) (delete-region start (match-beginning 0)))))) (defun planner-rss-limit-items (limit) "Delete RSS items past the LIMIT-th item." (when limit (widen) (goto-char (point-min)) (while (and (> limit -1) (re-search-forward "" nil t)) (setq limit (1- limit))) (when (= limit -1) (let ((start (match-beginning 0))) (re-search-forward "" nil t) (delete-region start (match-beginning 0)))))) (defun planner-publish-markup-note-rss () "Replace note with RSS 2.0 representation of note data. Borrowed heavily from Sacha's personal configs." (save-restriction (narrow-to-region (save-excursion (beginning-of-line) (point)) (or (save-excursion (and (re-search-forward "\\|" nil t) (match-beginning 0))) (point-max))) (let ((info (planner-current-note-info t))) (delete-region (point-min) (point-max)) (muse-insert-markup "\n" "" (muse-publish-escape-specials-in-string (planner-note-title info)) "\n" "" (concat planner-rss-base-url (muse-page-name) ".html#" (planner-note-anchor info)) "\n" "" (concat planner-rss-base-url (muse-page-name) ".html#" (planner-note-anchor info)) "\n") (when (planner-note-body info) (muse-insert-markup "\n")) (when (planner-note-date info) (muse-insert-markup "" (let ((system-time-locale "C") (timestamp (planner-note-timestamp info)) (date (planner-filename-to-calendar-date (planner-note-date info))) (minutes) (hour) (day) (month) (year)) (format-time-string "%a, %d %b %Y %T %Z" (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" timestamp) (let ((hour (string-to-number (match-string 1 timestamp))) (minutes (string-to-number (match-string 2 timestamp))) (month (nth 0 date)) (day (nth 1 date)) (year (nth 2 date))) (encode-time 0 minutes hour day month year))))) "\n")) (muse-insert-markup "\n")))) (defcustom planner-publish-markup-rss-functions '((note . planner-publish-markup-note-rss)) "An alist of style types to custom functions for that kind of text for RSS. For more on the structure of this list, see `muse-publish-markup-functions'." :type '(alist :key-type symbol :value-type function) :group 'planner-publish) (unless (assoc "planner-rss" muse-publishing-styles) (muse-derive-style "planner-rss" "planner-xml" :functions 'planner-publish-markup-rss-functions :header "" :footer "" :prefix planner-rss-base-url) (muse-derive-style "planner-rss-info" "planner-html" :header "" :footer "" :prefix planner-rss-base-url)) (provide 'planner-rss) ;;; planner-rss.el ends here planner-el/planner-schedule.el000066400000000000000000000060171226462314700167010ustar00rootroot00000000000000;;; planner-schedule.el --- Schedule integration for the Emacs Planner ;; Copyright (C) 2001, 2004, 2008 Free Software Foundation, Inc. ;; Author: John Wiegley ;; Keywords: planner, timeclock ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This module allows you to project task completion time. ;; Tasks should be of the form ;; #A0 _ 2h Do something ;; #B0 _ 1h30m Do something ;; #B0 _ 2d Do something ;; #B0 _ 2w Do something ;; #B0 _ 10s Do something ;; s: seconds, m: minutes, h: hours, d: days, w: weeks ;; You can find schedule.el in the contrib directory of Planner. ;;; Code: (require 'planner) (require 'schedule) (defun planner-schedule-task-estimate (info) "Return a time estimate for task (INFO) completion, in seconds." (when (string-match "\\`\\s-*\\([0-9]+[smhdw]\\)" (planner-task-description info)) (schedule-duration-to-seconds (match-string 1 (planner-task-description info))))) (defun planner-schedule-end-projection () "Show when today's task load will be finished, according to estimates." (require 'schedule) (schedule-initialize) (save-excursion (let ((now (schedule-completion-time (current-time) 0)) spent remaining slippage finish) (goto-char (point-min)) (while (re-search-forward "^#[A-C]" nil t) (let* ((task (planner-current-task-info)) (estimate (planner-schedule-task-estimate task))) (when estimate (setq now (schedule-completion-time now estimate))))) now))) ;;;###autoload (defun planner-schedule-show-end-project () "Display the estimated project completion time." (interactive) (message (format-time-string "%c" (planner-schedule-end-projection)))) (condition-case nil (let ((map planner-mode-map)) (define-key map (kbd "C-c RET") 'planner-schedule-show-end-project) (define-key map "\C-c\C-m" 'planner-schedule-show-end-project) (if (featurep 'xemacs) (define-key map (kbd "C-c C-T C-e") 'planner-schedule-show-end-project) (define-key map (kbd "C-c C-S-t C-e") 'planner-schedule-show-end-project))) (error (message "Could not bind schedule keys in planner mode"))) (provide 'planner-schedule) ;;; planner-schedule.el ends here planner-el/planner-tasks-overview.el000066400000000000000000000306611226462314700201000ustar00rootroot00000000000000;;; planner-tasks-overview.el --- Task summary for planner.el ;; ;; Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. ;; Emacs Lisp Archive Entry ;; Filename: planner-tasks-overview.el ;; Keywords: hypermedia ;; Author: Sandra Jean Chua (Sacha) ;; Description: Task overview for planner.el files ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_ + Commentary: ;; You can use `planner-tasks-overview' to see a list of tasks between ;; two dates. `planner-tasks-overview-jump' jumps to the linked task. ;; To change the sort order, invoke the following functions: ;; `planner-tasks-overview-sort-by-date' ;; `planner-tasks-overview-sort-by-plan' ;; `planner-tasks-overview-sort-by-category' ;; `planner-tasks-overview-sort-by-status' ;; ;; This file was inspired by Markus Hoenicka's ;; http://www.mhoenicka.de/software/hacks/tasklist.html and Frederick ;; Fouvry's Lisp port of tasklist.pl. ;;;_ + Contributors ;; Andrew J. Korty (ajk AT iu DOT edu) provided a patch that corrected ;; a typo in the keymap. ;; Yann Hodique helped port this to Muse. ;;; Code: (require 'planner) (defvar planner-tasks-overview-mode-map (let ((map (make-sparse-keymap))) (define-key map "1" 'planner-tasks-overview-sort-by-date) (define-key map "2" 'planner-tasks-overview-sort-by-plan) (define-key map "3" 'planner-tasks-overview-sort-by-priority) (define-key map "4" 'planner-tasks-overview-sort-by-status) (define-key map "j" 'planner-tasks-overview-jump) (define-key map "o" 'planner-tasks-overview) (define-key map [tab] 'planner-next-reference) (define-key map [(control ?i)] 'planner-next-reference) (if (featurep 'xemacs) (define-key map [(shift tab)] 'planner-previous-reference) (define-key map [(shift iso-lefttab)] 'planner-previous-reference) (define-key map [(shift control ?i)] 'planner-previous-reference)) map) "Keymap for planner task overview buffers.") (define-derived-mode planner-tasks-overview-mode planner-mode "Overview" "Planner tasks overview. \\{planner-tasks-overview-mode-map}") (defvar planner-tasks-overview-data nil "Task data.") (make-variable-buffer-local 'planner-tasks-overview-data) (defvar planner-tasks-overview-buffer "*planner tasks overview*" "Buffer name.") ;;;###autoload (defun planner-tasks-overview (start end) "Display a task overview from START to END." (interactive (list (planner-read-date) (planner-read-date))) (when (get-buffer planner-tasks-overview-buffer) (kill-buffer planner-tasks-overview-buffer)) (with-current-buffer (get-buffer-create planner-tasks-overview-buffer) (planner-tasks-overview-mode) (setq planner-tasks-overview-data (planner-extract-tasks (planner-get-day-pages start end))) (setq truncate-lines t) (set (make-local-variable 'truncate-partial-width-windows) t) (planner-tasks-overview-sort-by-date) (switch-to-buffer (current-buffer)))) ;;;###autoload (defun planner-tasks-overview-jump-other-window () "Display the task under point in a different window." (interactive) (planner-tasks-overview-jump t)) ;;;###autoload (defun planner-tasks-overview-jump (&optional other-window) "Display the task under point." (interactive "P") (when other-window (switch-to-buffer-other-window (current-buffer))) (let* ((info (get-text-property (point) 'info)) (page (or (elt info 2) (elt info 3)))) (planner-find-file page) (goto-char (point-min)) (widen) (when (re-search-forward (concat "#[A-C][0-9]*\\s-+.\\s-+" (regexp-quote (elt info 4))) nil t) (goto-char (planner-line-beginning-position))))) (defun planner-tasks-overview-sort-by-field (field) "Sort by FIELD." (interactive) (setq planner-tasks-overview-data (sort planner-tasks-overview-data (lambda (a b) (cond ((null (elt a field)) nil) ((null (elt b field)) t) ((string< (elt a field) (elt b field))))))) (planner-tasks-overview-insert)) (defun planner-tasks-overview-sort-by-date () "Sort by date." (interactive) (planner-tasks-overview-sort-by-field 8)) (defun planner-tasks-overview-sort-by-plan () "Sort by plan." (interactive) (planner-tasks-overview-sort-by-field 7)) (defun planner-tasks-overview-sort-by-priority () "Sort by plan." (interactive) (planner-tasks-overview-sort-by-field 1)) (defun planner-tasks-overview-sort-by-status () "Sort by status." (interactive) (setq planner-tasks-overview-data (sort planner-tasks-overview-data (lambda (a b) (if (string= (elt b 3) (elt a 3)) (string< (elt a 1) (elt b 1)) (member (elt b 3) (member (elt a 3) '("_" "o" "D" "P" "X" "C"))))))) (planner-tasks-overview-insert)) (defun planner-tasks-overview-insert () "Insert the textual representation for `planner-tasks-overview-data'." (with-current-buffer (get-buffer-create "*planner tasks overview*") (setq muse-current-project (muse-project planner-project)) (setq buffer-read-only nil) (erase-buffer) (let (last-date last-plan) (mapcar (lambda (item) (let* ((date (planner-task-date item)) (plan (planner-task-plan item)) (text (format "%10s | %s | %s %s | %s\n" (if date (planner-make-link date (format "%-10.10s" (if (string= last-date date) "\"\"" date))) (format "%-10.10s" "")) (if plan (planner-make-link plan (format "%-20.20s" (if (string= last-plan plan) "\"\"" plan))) (format "%-20.20s" "")) (planner-task-priority item) (planner-task-status item) (planner-task-description item)))) (add-text-properties 0 (length text) (list 'info item) text) (insert text) (setq last-date date) (setq last-plan plan))) planner-tasks-overview-data) (goto-char (point-min)) (setq buffer-read-only t)))) ;; Improvements: sort? ;;;###autoload (defun planner-tasks-overview-show-summary (&optional file-list) "Count unscheduled, scheduled, and completed tasks for FILE-LIST. If called with an interactive prefix, prompt for the page(s) to display. planner-multi is required for multiple pages." (interactive (list (if current-prefix-arg (planner-file-alist nil (if (featurep 'planner-multi) (mapcar 'planner-link-base (planner-multi-split (planner-read-non-date-page (planner-file-alist)))) (list (planner-read-non-date-page (planner-file-alist)))))))) (let (data total) (with-planner (setq data (planner-tasks-overview-get-summary file-list)) (with-current-buffer (get-buffer-create "*planner tasks overview*") (setq buffer-read-only nil) (erase-buffer) (setq total (+ (elt data 0) (elt data 1) (elt data 2))) (insert (format "Total unfinished, unscheduled tasks : %3d (%6.2f%%)\n" (elt data 0) (/ (elt data 0) (* 0.01 total))) (format "Total unfinished, scheduled tasks : %3d (%6.2f%%)\n" (elt data 1) (/ (elt data 1) (* 0.01 total))) (format "Total finished tasks : %3d (%6.2f%%)\n\n" (elt data 2) (/ (elt data 2) (* 0.01 total)))) (insert (format "%-40s | Unsched | Sched | Complete | Total\n" "Plan page")) (mapcar (lambda (row) (let ((row-total (* 0.01 (+ (elt row 1) (elt row 2) (elt row 3))))) (insert (format "%s | %3d %3.0f%% | %3d %3.0f%% | %3d %3.0f%% | %3d %3.0f%%\n" (planner-make-link (elt row 0) (format "%-40.40s" (elt row 0))) (elt row 1) (/ (elt row 1) row-total) (elt row 2) (/ (elt row 2) row-total) (elt row 3) (/ (elt row 3) row-total) (+ (elt row 1) (elt row 2) (elt row 3)) (/ (+ (elt row 1) (elt row 2) (elt row 3)) (* 0.01 total)))))) (elt data 3)) (setq muse-current-project (muse-project planner-project)) (planner-mode) (switch-to-buffer (current-buffer)))))) ;; Unfinished Finished % Complete ;; Unscheduled Scheduled (defun planner-tasks-overview-get-summary (&optional file-list) "Return a summary of tasks on pages in FILE-LIST. List is of the form (total-unfinished-unscheduled total-unfinished-scheduled total-finished data), where data is a list of the form (plan unfinished-unscheduled unfinished-scheduled finished)." (let ((total-unfinished-unscheduled 0) (total-unfinished-scheduled 0) (total-finished 0) list) (unless file-list (setq file-list (planner-file-alist))) (with-temp-buffer (with-planner (while file-list (unless (string-match planner-date-regexp (car (car file-list))) (let ((unfinished-unscheduled 0) (unfinished-scheduled 0) (finished 0)) (erase-buffer) (insert-file-contents (cdr (car file-list))) (goto-char (point-min)) (while (re-search-forward planner-task-regexp nil t) (let ((info (planner-task-info-from-string (car (car file-list)) (buffer-substring (planner-line-beginning-position) (planner-line-end-position))))) (cond ((or (string= (planner-task-status info) "X") (string= (planner-task-status info) "C")) (setq finished (1+ finished))) ((planner-task-date info) (setq unfinished-scheduled (1+ unfinished-scheduled))) (t (setq unfinished-unscheduled (1+ unfinished-unscheduled)))))) (setq list (cons (list (car (car file-list)) unfinished-unscheduled unfinished-scheduled finished) list)) (setq total-unfinished-unscheduled (+ total-unfinished-unscheduled unfinished-unscheduled)) (setq total-unfinished-scheduled (+ total-unfinished-scheduled unfinished-scheduled)) (setq total-finished (+ total-finished finished)))) (setq file-list (cdr file-list))))) (list total-unfinished-unscheduled total-unfinished-scheduled total-finished list))) (provide 'planner-tasks-overview) ;;; planner-tasks-overview.el ends here planner-el/planner-timeclock-summary-proj.el000066400000000000000000000215071226462314700215230ustar00rootroot00000000000000;;; planner-timeclock-summary-proj.el --- timeclock project for the Emacs planner ;; Copyright (C) 2004, 2008 Pascal Quesseveur ;; Parts copyright (C) 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Trent Buck ;; Author: Pascal Quesseveur ;; Time-stamp: <2004-12-17 18:39> ;; Description: Summary timeclock of a project ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; planner-timeclock-summary-proj.el produces timeclock reports for planner ;; files. That package uses `timeclock-project-alist' and ;; `timeclock-seconds-to-string' from timeclock. ;; To use, call `planner-timeclock-summary-proj-current' from a ;; project page. The report is inserted at the current position in the ;; buffer. The function `planner-timeclock-summary-proj-section' does ;; the same but the report is inserted inside a section called "* ;; Report". ;; You might want to add ;; ;; (planner-timeclock-summary-proj-insinuate) ;; ;; to your planner config, which will cause the timeclock summary to ;; be updated every time a Planner file is written. ;;; Contributors ;; Trent Buck overhauled the code for Planner-Muse. ;; Marko Schütz provided a bugfix. ;;; CODE (require 'planner-timeclock) (require 'planner-timeclock-summary) ;;; User variables ;;; Code: (defcustom planner-timeclock-workdays-per-week 5 "Number of work days per week." :type 'integer :group 'planner-timeclock-summary) (defcustom planner-timeclock-workhours-per-day 8 "Number of work hours per day." :type 'integer :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-proj-header "Report" "Header for the timeclock summary project section in a plan page." :type 'string :group 'planner-timeclock-summary) ;;;; User variables stop here (defun planner-timeclock-summary-proj-section () "Update the secion corresponding with `planner-timeclock-summary-proj-header' in the current plan page. The section is updated only if it exists." (interactive) (save-excursion (save-restriction (when (planner-narrow-to-section planner-timeclock-summary-proj-header) (let ((thepage (planner-page-name))) (when (and thepage ;; Don't edit unless we're in a task page. (not (string-match planner-date-regexp thepage))) (delete-region (point-min) (point-max)) (insert "* " planner-timeclock-summary-proj-header "\n") (planner-timeclock-summary-proj-report thepage) (insert "\n\n"))))))) ;;;###autoload (defun planner-timeclock-summary-proj-all () "Insert time report for all projects in the current buffer." (interactive) (planner-timeclock-summary-proj-report nil)) ;;;###autoload (defun planner-timeclock-summary-proj-current () "Insert time report for the current project in the current buffer." (interactive) (let ((project (planner-page-name))) (planner-timeclock-summary-proj-report project))) ;;;###autoload (defun planner-timeclock-summary-proj-report (project) "Insert time report for PROJECT in the current buffer." (interactive "sProject: ") (insert (planner-timeclock-proj-build-report (planner-timeclock-proj-make-alist project)))) (defun planner-timeclock-proj-build-report (proj-alist) "Return time report for PROJ-ALIST. The time report is formatted as Duration || Task duration | TASK 0 duration | TASK 1 duration | TOTAL." (let ((str "\n Duration || Task") (total-duration 0)) (while proj-alist (let* ((proj-entry (car proj-alist)) (duration (cdr proj-entry))) (setq str (concat str "\n" (format "%18s" (planner-timeclock-proj-seconds-to-string duration)) " | " (format "%s" (car proj-entry)))) (setq total-duration (+ duration total-duration)) (setq proj-alist (cdr proj-alist)))) (concat str "\n" (format "%18s" (planner-timeclock-proj-seconds-to-string total-duration)) " | " "TOTAL"))) (defun planner-timeclock-proj-make-alist (proj-name) "Return an association list for PROJ-NAME. Each association is of the form (TASK . DURATION). TASK is a task name defined inside PROJ-NAME and DURATION is the total time computed for that task. When PROJ-NAME is nil, each TASK is a project name, and DURATION is the time spent on that project." (let ((projects (planner-timeclock-proj-entries proj-name)) (proj-alist)) ;; Looping on project data. The project is made of tasks, and for each ;; task there can be several time intervals. (while projects (let* ((entry (car projects)) (task (car entry)) (task-data (cdr entry)) (task-time 0)) ;; We compute the time spent on task TASK (setq task-time 0) (while task-data (let ((task-entry (car task-data))) (progn (setq task-time (+ task-time (timeclock-entry-length task-entry))) (setq task-data (cdr task-data))))) ;; compute the name (if (string-match ": *" task) (if (and (< (match-end 0) (length task)) proj-name) (setq task (substring task (match-end 0))) (setq task (substring task 0 (match-beginning 0))))) ;; record the cons (task . time) (if proj-alist (let ((proj-time 0) (proj-data-cell (assoc task proj-alist))) (if proj-data-cell (progn (setq proj-time (cdr proj-data-cell)) (setcdr proj-data-cell (+ task-time proj-time))) (add-to-list 'proj-alist (cons task task-time)))) (setq proj-alist (list (cons task task-time)))) (setq projects (cdr projects)))) proj-alist)) (defun planner-timeclock-proj-entries (proj-name) "Return entries from `timeclock-project-alist' for PROJ-NAME. If PROJ-NAME is nil, return `timeclock-project-alist'." (let ((projects) (entry-list (timeclock-project-alist))) ;; Looping on entries. Each entry is in the form (PROJECT (TASKS ;; DATA)). We keep only entries for which PROJECT-NAME matches ;; PROJECT. (if (not proj-name) entry-list (while entry-list (let* ((proj (car entry-list)) (proj-entry-name (car proj))) (if (and proj-name proj-entry-name (string-match (concat "^\\[\\[" proj-name "\\]\\]") proj-entry-name)) (if projects (add-to-list 'projects proj) (setq projects (list proj)))) (setq entry-list (cdr entry-list)))) projects))) (defun planner-timeclock-summary-proj-insinuate () "Insinuate planner-timeclock-summary-proj with the rest of Planner." (add-hook 'planner-mode-hook (lambda () (add-hook (if (boundp 'write-file-functions) 'write-file-functions 'write-file-hooks) 'planner-timeclock-summary-proj-section nil t)))) (defun planner-timeclock-proj-seconds-to-string (seconds) "Convert the floating point number SECONDS to a string. The string is in the form [WWw] [DDd] hh:ss." (let* ((workday (* planner-timeclock-workhours-per-day 3600)) (days (floor (/ seconds workday))) (secs (floor (- seconds (* days workday))))) (if (> days planner-timeclock-workdays-per-week) (let ((weeks (/ days planner-timeclock-workdays-per-week)) (dys (% days planner-timeclock-workdays-per-week))) (if (> dys 0) (format "%dw %dd %s" weeks dys (timeclock-seconds-to-string secs)) (format "%dw %s" weeks (timeclock-seconds-to-string secs)))) (if (> days 0) (format "%dd %s" days (timeclock-seconds-to-string secs)) (format "%s" (timeclock-seconds-to-string secs)))))) (provide 'planner-timeclock-summary-proj) ;;; planner-timeclock-summary-proj.el ends here planner-el/planner-timeclock-summary.el000066400000000000000000000624521226462314700205570ustar00rootroot00000000000000;;; planner-timeclock-summary.el --- timeclock summary for the Emacs planner ;; ;; Copyright (C) 2004, 2005, 2008 Dryice Dong Liu . All rights reserved. ;; Parts copyright (C) 2004, 2005, 2008 Chris Parsons (chris.p AT rsons.org) ;; Parts copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Peter K. Lee ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center ;; Keywords: emacs planner timeclock report summary ;; Author: Dryice Liu ;; Time-stamp: <16/07/2005 21:43:50 Yann Hodique> ;; Description: Summary timeclock of a day ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; planner-timeclock-summary.el produces timeclock reports for planner ;; files. ;; ;; There are two ways you can use it: ;; ;; 1. Display a temporary buffer ;; ;; Call `planner-timeclock-summary-show' and Emacs will ask you which ;; day's summary do you want. Choose the date as anywhere else of ;; Emacs planner, and a tempory buffer will be displayed with the ;; timeclock summary of that day. ;; ;; 2. Rewrite sections of your planner ;; ;; Choose this approach if you want timeclock summary to be in their ;; own section and you would like them to be readable in your plain ;; text files even outside Emacs. Caveat: The timeclock summary ;; section should already exist in your template and will be rewritten ;; when updated. Tip: Add `planner-timeclock-summary-section' ;; (default: "Timeclock") to your `planner-day-page-template'. ;; ;; To use, call `planner-timeclock-summary-update' in the planner day ;; page to update the section. If you want rewriting to be ;; automatically performed, call `planner-timeclock-summary-insinuate' ;; in your .emacs file ;;; REQUIRE ;; to make a nice text table, you need align.el from ;; http://www.newartisans.com/johnw/Emacs/align.el ;;; TODO ;; - sort? ;;; Contributors: ;; Chris Parsons submitted a patch that allows date ranges when ;; summarizing data. ;; Peter K. Lee made it so that even if there is an error with timelog ;; file (which happens frequently), you don't lose the * Timeclock ;; section, among other fixes. (require 'planner-timeclock) (require 'align) (require 'time-date) (eval-and-compile ;; Workaround for Win2k time-date.el bug reported by David Lord (unless (fboundp 'time-subtract) (defalias 'time-subtract 'subtract-time))) ;; User functions: ;; planner-timeclock-summary-insinuate ;; planner-timeclock-summary-update ;; planner-timeclock-summary-show ;; planner-timeclock-summary-show-range ;; planner-timeclock-summary-show-filter ;; planner-timeclock-summary-show-range-filter ;;; Code: ;;;_+ User variables (defgroup planner-timeclock-summary nil "Timeclock reports for planner.el." :prefix "planner-timeclock-summary" :group 'planner) (defcustom planner-timeclock-summary-section "Timeclock" "Header for the timeclock summary section in a plan page." :type 'string :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-buffer "*Planner Timeclock Summary*" "Buffer name for timeclock reports from `planner-timeclock-summary-show'." :type 'string :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-not-planned-string "Not Planned" "Project name for `timeclock-in' tasks without a project name." :type 'string :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-placeholder-char "." "Placeholder for blank cells in the report table. If there are have blank cells in a simple table, the generated HTML table will mess up. This character will be used as a placeholder." :type 'character :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-include-sub-plan-pages-flag nil "Non-nil means include 'sub plan pages' when doing plan page reports. If non-nil, when updating timeclock reports on plan pages we will also include plan pages which have this page's name as a prefix. If nil, only exact matches will be included. For example: if nil, on a plan page called 'Personal' we would only include timeclock data marked as 'Personal' (this is the default behaviour). If non-nil, we would additionally include 'PersonalHomework', 'PersonalYodeling' etc." :type 'boolean :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-summary-string "\n\nDay began: %B, Day ended: %E\nTime elapsed: %S, \ Time clocked: %C\nTime clocked ratio: %R\n" "The string below the report table. %B the first time checked in the day %L the last time checked in the day %E the last time checked in the day, or the current time if it's today %s span, the difference between %B and %L %S span, the difference between %B and %E %C the total time clocked %r clocked/%s %R clocked/%S" :type 'string :group 'planner-timeclock-summary) ;;;_+ Internal variables and utility functions (defvar planner-timeclock-summary-empty-cell-string "=====" "Internal use, don't touch.") (defvar planner-timeclock-summary-total-cell-string "=======" "Internal use, don't touch.") (defun planner-timeclock-within-date-range (start-date end-date test-date) "Return non-nil if START-DATE and END-DATE contain TEST-DATE. Dates should be of the form YYYY/MM/DD or YYYY.MM.DD." (not (or (string< test-date start-date) (string< end-date test-date)))) ;;;_+ Data extraction (defun planner-timeclock-summary-day-range-entry (start-date end-date &optional filter) "Return the data between START-DATE and END-DATE (inclusive) START-DATE and END-DATE should be strings of the form YYYY/MM/DD. If FILTER is a regexp, only plan pages matching that regexp will be included. If FILTER is a function, it will be called with the current timeclock item, and the line considered if the function returned non-nil. Use the format specified in timeclock.el." (let ((day-list (timeclock-day-alist)) entry-list item day) (while day-list (setq day (car day-list)) (setq day-list (cdr day-list)) (when (and (or (not start-date) (planner-timeclock-within-date-range start-date end-date (car day)))) (setq entry-list (append (cddr day) entry-list)))) (unless (or (null filter) (and (not (functionp filter)) (string= filter ""))) (setq entry-list (delq nil (mapcar (lambda (item) (when (cond ((stringp filter) (and (nth 2 item) (string-match filter (nth 2 item)))) ((functionp filter) (funcall filter item))) item)) entry-list)))) (setq entry-list (cons (cond ((not start-date) (prin1-to-string filter)) ((string= start-date end-date) start-date) (t (concat start-date " - " end-date))) entry-list)))) (defun planner-timeclock-summary-one-day-entry (date) "Return the data associated with DATE. DATE should be a string of the form YYYY/MM/DD." (planner-timeclock-summary-day-range-entry date date)) (defun planner-timeclock-summary-one-day-entry-no-date (date) "Return the entries for DATE. DATE should be a string of the form YYYY/MM/DD." (let ((entry-list (planner-timeclock-summary-day-range-entry date date))) (cdr entry-list))) (defun planner-timeclock-summary-one-day-alist (date) "Return the entries for DATE as an alist. DATE should be a string of the form YYYY/MM/DD." (let ((entry-list (planner-timeclock-summary-day-range-entry date date))) (cddr entry-list))) (defun planner-timeclock-summary-day-range-alist (start-date end-date) "Return the entries between START-DATE and END-DATE (inclusive) as an alist. START-DATE and END-DATE should be strings of the form YYYY/MM/DD." (let ((entry-list (planner-timeclock-summary-day-range-entry start-date end-date))) (cddr entry-list))) (defun planner-timeclock-summary-extract-data (data-list) "Return the timeclock data for dates included in DATA-LIST." (with-planner (let (target-data task-data entry) (while data-list (setq entry (car data-list)) (setq data-list (cdr data-list)) (setq task-data (planner-timeclock-task-info entry)) (let* ((plan (planner-timeclock-task-plan task-data)) (entry-project-name (if plan (planner-link-base plan) planner-timeclock-summary-not-planned-string)) (entry-task-name (planner-timeclock-task-description task-data)) (entry-task-length (planner-timeclock-task-length task-data))) ;; total time (if target-data (setcar target-data (+ (car target-data) entry-task-length)) (setq target-data (list entry-task-length))) ;; updating project (let ((projects (cdr target-data)) project-found project) (while projects (setq project (car projects)) (let ((project-name (caar project)) (project-time (car (cdar project)))) (if (and project-name (string-equal project-name entry-project-name)) ;; the same project has been recorded, updating tasks (let ((tasks (cdr project)) task-found task) (while tasks (setq task (car tasks)) (let ((task-name (car (cdr (cdr task))))) (if (and task-name (string-equal task-name entry-task-name)) ;; the same task has been recorded, add ;; time (progn (setcar task (+ (car task) entry-task-length)) (setq tasks nil) (setq task-found t)) (setq tasks (cdr tasks))))) ;; make a new task record (if (not task-found) (setcar projects (add-to-list 'project (list entry-task-length 0 entry-task-name) t))) ;; update project time (setcar (cdar project) (+ project-time entry-task-length)) (setq projects nil) (setq project-found t)) (setq projects (cdr projects))))) ;; make a new project record (if (not project-found) (add-to-list 'target-data (list (list entry-project-name entry-task-length 0) (list entry-task-length 0 entry-task-name)) t))))) target-data))) (defun planner-timeclock-summary-extract-data-day (date) "Prepare the data for the summary for DATE. Read `timeclock-file' and return an alist. The list will be of the form: (TotalTime (((Project1Name Project1Time Project1Ratio) (p1t1time p1t1ratio p1t1name) (p1t2time p1t2ratio p1t2name) ...) ((p2name p2time p2ratio) ...)))" (planner-timeclock-summary-extract-data (planner-timeclock-summary-one-day-alist date))) (defun planner-timeclock-summary-make-summary-string-range (start-date end-date total &optional filter) "Use `planner-timeclock-summary-summary-string' from START-DATE to END-DATE. Dates are in format YYYY/MM/DD. TOTAL is the total time clocked today, in seconds. If FILTER is a regexp, only plan pages matching that regexp will be included. If FILTER is a function, it will be called with the current timeclock item, and the line considered if the function returned non-nil." (let* ((target-string planner-timeclock-summary-summary-string) (data (planner-timeclock-summary-day-range-entry start-date end-date filter)) begin end last span2 span (case-fold-search nil)) (setq begin (timeclock-day-begin data)) (setq last (timeclock-day-end data)) (if (string-equal end-date (format-time-string "%Y/%m/%d")) (setq end (current-time)) (setq end last)) (setq span (timeclock-time-to-seconds (time-subtract last begin))) (setq span2 (timeclock-time-to-seconds (time-subtract end begin))) (mapcar (lambda (replacement) (setq target-string (planner-replace-regexp-in-string (car replacement) (cdr replacement) target-string t t))) (list (cons "%B" (format-time-string "%H:%M:%S" begin)) (cons "%E" (format-time-string "%H:%M:%S" end)) (cons "%L" (format-time-string "%H:%M:%S" last)) (cons "%s" (timeclock-seconds-to-string span t)) (cons "%S" (timeclock-seconds-to-string span2 t)) (cons "%C" (timeclock-seconds-to-string total t)) (cons "%r" (format "%2.1f%%" (* 100 (/ total span)))) (cons "%R" (format "%2.1f%%" (* 100 (/ total span2)))))) target-string)) (defun planner-timeclock-summary-make-summary-string (date total) "Convenience function for getting the summary string for DATE. DATE is in the form YYYY/MM/DD. TOTAL is the total time clocked today, in seconds." (planner-timeclock-summary-make-summary-string-range date date total)) (defun planner-timeclock-summary-calculate-ratio-day (start-date &optional end-date filter) "Calculate time ratio for START-DATE to END-DATE. If FILTER is a regexp, only plan pages matching that regexp will be included. If FILTER is a function, it will be called with the current timeclock item, and the line considered if the function returned non-nil." (when (not end-date) (setq end-date start-date)) (let (target-data) (setq target-data (planner-timeclock-summary-extract-data (cdr (planner-timeclock-summary-day-range-entry start-date end-date filter)))) (let ((total (car target-data)) (projects (cdr target-data))) (while projects (let ((project (car projects)) (tasks (cdar projects))) (setcar (cdr (cdar project)) (/ (car (cdar project)) total)) (while tasks (let ((task (car tasks))) (setcar (cdr task) (/ (car task) total)) (setq tasks (cdr tasks)))) (setq projects (cdr projects))))) target-data)) ;;;_+ Presentation (defun planner-timeclock-summary-make-text-table-day (start-date &optional end-date filter hide-summary) "Make the summary table for START-DATE to END-DATE using plain text. If FILTER is a regexp, only plan pages matching that regexp will be included. If FILTER is a function, it will be called with the current item, and the line considered if the function returned non-nil. If START-DATE is nil, then it will ignore the date information and return data for everything. If HIDE-SUMMARY is non-nil, do not include the summary." (unless end-date (setq end-date start-date)) (let (source-list) (setq source-list (planner-timeclock-summary-calculate-ratio-day start-date end-date filter)) (let ((projects (cdr source-list)) (total (car source-list)) (project-name-format "20.20s")) (if total (with-temp-buffer (erase-buffer) (insert "Project | Time | Ratio | Task\n") (while projects (let ((project-data (caar projects)) (tasks (cdar projects)) (first-task t)) (mapcar (lambda (task) (let* ((project-link (car project-data)) (desc-link (if first-task (if (or (null project-link) (string= project-link planner-timeclock-summary-not-planned-string)) planner-timeclock-summary-not-planned-string (planner-make-link project-link)) planner-timeclock-summary-placeholder-char))) (setq first-task nil) (insert (format "%s | %8s | %4s%% | %s\n" desc-link (timeclock-seconds-to-string (car task) t) (format "%2.1f" (* 100 (cadr task))) (car (cddr task)))))) tasks) (insert (format "Total: | %8s | %4s%% | %s\n" (timeclock-seconds-to-string (cadr project-data) t) (format "%2.1f" (* 100 (nth 2 project-data))) planner-timeclock-summary-placeholder-char))) (setq projects (cdr projects))) (planner-align-table) (goto-char (point-max)) (unless hide-summary (insert (planner-timeclock-summary-make-summary-string-range start-date end-date total filter))) (buffer-string)) "No entries\n")))) ;;;###autoload (defun planner-timeclock-summary-insinuate () "Automatically call `planner-timeclock-summary-update'. This function is called when the day page is saved." (add-hook 'planner-mode-hook (lambda () (add-hook (cond ((boundp 'write-file-functions) 'write-file-functions) ((boundp 'local-write-file-hooks) 'local-write-file-hooks) ((boundp 'write-file-hooks) 'write-file-hooks)) 'planner-timeclock-summary-update nil t)))) ;;;###autoload (defun planner-timeclock-summary-update () "Update `planner-timeclock-summary-section'. in the current day page. The section is updated only if it exists." (interactive) (save-excursion (save-restriction (when (planner-narrow-to-section planner-timeclock-summary-section) (delete-region (point-min) (point-max)) (let ((thepage (planner-page-name))) (insert "* " planner-timeclock-summary-section "\n\n") (insert (if (and thepage (string-match planner-date-regexp thepage)) (planner-timeclock-summary-make-text-table-day (planner-replace-in-string thepage "[\\.\\-]" "/" t thepage t t)) (planner-timeclock-summary-make-text-table-day nil nil (concat "^" thepage (unless planner-timeclock-summary-include-sub-plan-pages-flag ":")) t)) " \n")))))) ;;;###autoload (defun planner-timeclock-summary-show (&optional date) "Display a buffer with the timeclock summary for DATE. Date is a string in the form YYYY.MM.DD." (interactive (list (planner-read-date))) (planner-timeclock-summary-show-range date date)) ;;;###autoload (defun planner-timeclock-summary-show-filter (filter date) "Show a timeclock report filtered by FILTER for DATE. If FILTER is a regexp, only plan pages matching that regexp will be included. If FILTER is a function, it will be called with the current timeclock item, and the line considered if the function returned non-nil. If called interactively, prompt for FILTER (a regexp) and DATE. DATE is a string in the form YYYY.MM.DD and can be nil." (interactive (list (read-string "Filter (regexp): " nil 'regexp-history) (planner-read-date))) (planner-timeclock-summary-show-range date date filter)) ;;;###autoload (defun planner-timeclock-summary-show-range-filter (filter start-date end-date) "Show a timeclock report filtered by FILTER for START-DATE to END-DATE. If FILTER is a regexp, only plan pages matching that regexp will be included. If FILTER is a function, it will be called with the current timeclock item, and the line considered if the function returned non-nil. If called interactively, prompt for FILTER (a regexp), START-DATE and END-DATE. Dates are strings in the form YYYY.MM.DD and can be nil." (interactive (list (read-string "Filter (regexp): " nil 'regexp-history) (planner-read-date "Start") (planner-read-date "End"))) (planner-timeclock-summary-show-range start-date end-date filter)) (defun planner-timeclock-summary-show-range (start-date end-date &optional filter) "Show a timeclock report for the date range START-DATE to END-DATE. If FILTER is a regexp, only plan pages matching that regexp will be included. If FILTER is a function, it will be called with the current timeclock item, and the line considered if the function returned non-nil. Dates are strings in the form YYYY.MM.DD and can be nil." (interactive (list (planner-read-date "Start") (planner-read-date "End"))) (switch-to-buffer (get-buffer-create planner-timeclock-summary-buffer)) (erase-buffer) (let ((muse-current-project (muse-project planner-project))) (insert "Timeclock summary report for " (if (string-equal start-date end-date) start-date (concat start-date " - " end-date)) "\n\n" (planner-timeclock-summary-make-text-table-day (planner-replace-regexp-in-string "[\\.\\-]" "/" start-date t t) (planner-replace-regexp-in-string "[\\.\\-]" "/" end-date t t) filter)) (planner-mode)) (goto-char (point-min))) ;;;_+ experimental code (defcustom planner-timeclock-summary-task-project-summary-string "*Project Summary*" "Task name for project summary." :type 'string :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-project-column-min-width 22 "Minimum width of the project column in the report table." :type 'integer :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-time-column-min-width 8 "Minimum width of the time column in the report table." :type 'integer :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-ratio-column-min-width 5 "Minimum width of the ratio column in the report table." :type 'integer :group 'planner-timeclock-summary) (defcustom planner-timeclock-summary-task-column-min-width 40 "Minimum width of the task column in the report table." :type 'integer :group 'planner-timeclock-summary) (defun planner-timeclock-summary-make-table-day (date start-point) "Format `planner-timeclock-summary-make-text-table-day' neatly. The report is prepared for DATE. START-POINT is not used." ;; (with-temp-buffer ;; (erase-buffer) (insert (planner-timeclock-summary-make-text-table-day date)) ;; (planner-mode) (redraw-display) (table-capture 42 (point-max) "|" "\n" 'left (list planner-timeclock-summary-project-column-min-width planner-timeclock-summary-time-column-min-width planner-timeclock-summary-ratio-column-min-width planner-timeclock-summary-task-column-min-width)) ;; make "=====" cell empty and span above ;; (goto-char (point-min)) ;; (while (search-forward ;; planner-timeclock-summary-empty-cell-string) ;; (beginning-of-line) ;; (kill-line) ;; (table-span-cell 'above)) ;; (buffer-string)) ) ;;;###autoload (defun planner-timeclock-summary-show-2 (&optional date) "Display a buffer with the timeclock summary for DATE. Date is a string in the form YYYY.MM.DD. It will be asked if not given." (interactive (planner-read-date)) (switch-to-buffer (get-buffer-create planner-timeclock-summary-buffer)) (erase-buffer) (let ((muse-current-project (muse-project planner-project))) (insert "Timeclock summary report for " date "\n\n") (planner-mode) (planner-timeclock-summary-make-table-day (planner-replace-regexp-in-string "[\\.\\-]" "/" date t t) (point))) (goto-char (point-min))) (defun planner-timeclock-summary-table-span-cell-left () "Merge the current cell with the one to the left." (table-span-cell 'left)) (defun planner-timeclock-summary-table-span-cell-above () "Merge the current cell with the one above it." (table-span-cell 'above)) (provide 'planner-timeclock-summary) ;;; planner-timeclock-summary.el ends here planner-el/planner-timeclock.el000066400000000000000000000227401226462314700170600ustar00rootroot00000000000000;;; planner-timeclock.el --- Timeclock integration for the Emacs Planner ;; Copyright (C) 2001, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Peter K. Lee ;; Author: John Wiegley ;; Keywords: planner, timeclock ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This module allows you to clock in and clock out of your projects. ;; You can also generate reports with the tag. ;; ;; timeclock.el is part of GNU Emacs. If you are using XEmacs, please ;; use the version in the contrib directory -- otherwise, just use the ;; version that comes with Emacs. ;;; Contributors: ;; Yann Hodique helped port this to Muse. ;; Peter K. Lee helped fix an issue involving planner-multi.el with ;; the Muse port. ;;; Code: (require 'planner) (require 'timeclock) (require 'easymenu) (require 'advice) (defvar planner-timeclock-current-task nil "Description of current task.") (defalias 'planner-timeclock-in 'planner-task-in-progress) (defadvice timeclock-out (after planner-timeclock activate) "Clear `planner-timeclock-current-task.'" (setq planner-timeclock-current-task nil)) (defun planner-timeclock-plan-string (task-info &optional plans) "Return the string for the plan part of the timeclock entry for TASK-INFO." (let ((plan-link (if (featurep 'planner-multi) ;; Remove the date links (planner-multi-make-link (or (planner-multi-filter-links planner-date-regexp (if plans (planner-multi-split plans) (planner-multi-task-link-as-list task-info)) t) (list (planner-task-plan task-info)))) (planner-make-link (or plans (planner-task-plan task-info)))))) (if plan-link (concat plan-link ": ") ""))) (defun planner-timeclock-task-marked (old-status new-status) "Clock out if the task description matches the one clocked in." (cond ((string= new-status "X") (when (and planner-timeclock-current-task (string= (planner-task-description (planner-current-task-info)) planner-timeclock-current-task) (timeclock-currently-in-p)) (timeclock-out 1))) ((string= new-status "P") (when (and planner-timeclock-current-task (string= (planner-task-description (planner-current-task-info)) planner-timeclock-current-task) (timeclock-currently-in-p)) (timeclock-out))) ((string= new-status "o") (let* ((task-info (planner-current-task-info)) (project (concat (planner-timeclock-plan-string task-info) (planner-task-description task-info)))) (if (timeclock-currently-in-p) (timeclock-change nil project) (timeclock-in nil project)) (setq planner-timeclock-current-task (planner-task-description task-info))))) t) (add-hook 'planner-mark-task-hook 'planner-timeclock-task-marked) (defadvice planner-replan-task (around planner-timeclock activate) "Edit the clocked in task as well." (let ((info (planner-current-task-info))) ad-do-it (with-current-buffer (find-file-noselect timeclock-file) (goto-char (point-min)) (while (re-search-forward (concat "^. [^ \n]+ [^ \n]+ " ;; make project match optional (for tasks added manually). "\\(" (regexp-quote (planner-timeclock-plan-string info)) "\\)?" (regexp-quote (planner-task-description info)) "$") nil t) (replace-match (save-match-data (planner-timeclock-plan-string nil (ad-get-arg 0))) t t nil 1)) (save-buffer) (kill-buffer (current-buffer))))) (defadvice planner-edit-task-description (around planner-timeclock activate) "Update the timelog as well. Warning! Do not have duplicate tasks!" (let ((info (planner-current-task-info))) (when (string= (planner-task-description info) planner-timeclock-current-task) (setq planner-timeclock-current-task (ad-get-arg 0))) ad-do-it (with-current-buffer (find-file-noselect timeclock-file) (goto-char (point-min)) (while (re-search-forward (concat "^. [^ \n]+ [^ \n]+ " (regexp-quote (planner-timeclock-plan-string info)) "\\(" (regexp-quote (planner-task-description info)) "\\)$") nil t) (replace-match (ad-get-arg 0) t t nil 1)) (save-buffer) (kill-buffer (current-buffer))))) ;;;###autoload (defun planner-colors-timeclock-report-tag (beg end) "Replace the region BEG to END with a timeclock report, colorizing the result." (require 'timeclock) (add-text-properties beg end (list 'display (with-temp-buffer (timeclock-generate-report muse-publishing-p) (buffer-string))))) (defun planner-publish-timeclock-report-tag (beg end) "Replace the region BEG to END with a timeclock report." (require 'timeclock) (delete-region beg end) (timeclock-generate-report muse-publishing-p) (add-text-properties beg (point) '(read-only t))) (add-hook 'muse-colors-markup-tags '("timeclock-report" nil nil nil planner-colors-timeclock-report-tag)) (add-hook 'muse-publish-markup-tags '("timeclock-report" nil nil nil planner-publish-timeclock-report-tag)) (defun planner-timeclock-task-plan (info) "Return the first plan page associated with INFO." (car (elt info 0))) (defun planner-timeclock-task-plan-as-list (info) "Return all the plan pages associated with INFO." (elt info 0)) (defun planner-timeclock-task-description (info) "Return the descrption associated with INFO." (elt info 1)) (defun planner-timeclock-task-length (info) "Return the length associated with INFO." (elt info 2)) (defun planner-timeclock-task-info (entry) "Parse ENTRY and return a list of the form (plan task length). See `timeclock-log-data' for the format of ENTRY. Note that the project field in `timeclock-log-data' is 'project: task' here." (let ((project (if (stringp entry) entry (timeclock-entry-project entry))) plan task) (when project (with-planner (cond ;; No plan, just the task ((string-match "^\\s-*:\\s-+" project) (setq task (substring project (match-end 0)))) ;; Single link ((string-match (concat "^\\(" muse-explicit-link-regexp "\\): ") project) (setq plan (list (match-string 1 project))) (setq task (substring project (match-end 0)))) ;; Multi link ((and (featurep 'planner-multi) (string-match (concat "^\\(\\(?:" muse-explicit-link-regexp "\\)" "\\(?:" planner-multi-separator "\\(?:" muse-explicit-link-regexp "\\)\\)*\\): ") project)) (setq task (substring project (match-end 0))) (setq plan (planner-multi-split (match-string 1 project)))) ;; Nothing whatsoever. (t (setq task project))) (list plan task (unless (stringp entry) (timeclock-entry-length entry))))))) (condition-case nil (let ((map planner-mode-map)) (define-key map "\C-c\C-i" 'planner-task-in-progress) (define-key map "\C-c\C-o" 'timeclock-out) (if (featurep 'xemacs) (progn (define-key map (kbd "C-c C-T C-i") 'planner-task-in-progress) (define-key map (kbd "C-c C-T C-o") 'timeclock-out)) (define-key map (kbd "C-c C-S-t C-i") 'planner-task-in-progress) (define-key map (kbd "C-c C-S-t C-o") 'timeclock-out))) (error (message "Could not bind timeclock keys in planner mode"))) (condition-case nil ;; XEmacs seems to be missing this function in some released ;; versions of XEmacs21. (if (fboundp 'easy-menu-create-menu) (easy-menu-add-item planner-mode-map '("Planner") (easy-menu-create-menu "Timeclock" '(["Clock into a task" planner-timeclock-in] ["Clock out" timeclock-out]))) (easy-menu-add-item planner-menu '("Timeclock") ["Clock into a task" planner-timeclock-in t] "Plan") (easy-menu-add-item planner-menu '("Timeclock") ["Clock out" timeclock-out t] "Plan"))) (provide 'planner-timeclock) ;;; planner-timeclock.el ends here planner-el/planner-trunk.el000066400000000000000000000330621226462314700162500ustar00rootroot00000000000000;;; planner-trunk.el --- Trunk tasks for the Emacs planner ;; ;; Copyright (C) 2005, 2008 Dryice Dong Liu . All rights reserved. ;; Parts copyright (C) 2005, 2008 Keith Amidon ;; Parts copyright (C) 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center ;; Keywords: emacs planner trunk group tasks ;; Authors: Dryice Liu ;; Keith Amidon ;; Description: trunk(group) tasks for the Emacs planner ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This file provides `planner-trunk-tasks', which groups the tasks ;; according to `planner-trunk-rule-list'. Please see the docstring ;; for details. Remember to customize `planner-trunk-rule-list' before ;; trying it out. ;; ;; It sorts and splits your tasks, adding a blank line between groups ;; of tasks. ;; ;; WARNING: planner-trunk will delete *ALL* non-task lines from the ;; tasks section of your plan page if it attempts to trunk ;; the tasks. Do NOT use it if you want to preserve this ;; information. ;;; Things that would be nice to do: ;; - Respect hidden outline sections when trunking and rehide after ;; trunk is complete if they are present. ;; - If point is in the tasks section, keep point on the same line. ;; Maybe can do by saving entire line text and searching for it ;; afterwards. Only problem is if it is whitespace only line. If ;; so, maybe can move cursor to previous non-whitespace line? Point ;; obviously shouldn't move if not in Tasks section. ;;; Contributors: ;; Keith Amidon worked on a number of aspects of this file. ;; Sergey Vlasov contributed a fix that corrected regexp syntax and ;; kept the "Tasks" string from being hard-coded. ;;; Code: (require 'planner) ;;; USER VARIABLES ----------------------------------------------------------- (defgroup planner-trunk nil "Grouping tasks for planner.el." :prefix "planner-trunk" :group 'planner) (defcustom planner-trunk-rule-list `(("\\`[0-9][0-9][0-9][0-9]\\.[0-9][0-9]\\.[0-9][0-9]\\'" nil ("HomeWork" "WorkStuff" "EmacsHack\\|PlannerHack"))) "List of rules for trunking tasks. Each rule is a sublist of the form: (PAGE-REGEXP COMPLETE-HEADING TRUNK-SECTIONS-LIST) PAGE-REGEXP is used to select the set of trunk sections that should be used. It is matched against the name of the current planner page. If no matching PAGE-REGEXP is found, no trunking is done. If there is more than one match, the first one in the list is used. If COMPLETE-HEADING is nil, completed and not completed tasks will be in the same trunk, sorted according to `planner-sort-tasks-key-function'. If it is a string, it is the name of a sub-heading of the tasks section under which to sort completed tasks separately, in which case it will be the last subsection of the tasks section of the page. Each element of TRUNK-SECTIONS-LIST describes a trunk of the page. Elements can either be a simple TASK-PLAN-REGEXP, or a sublist of the form: (TASK-PLAN-REGEXP TRUNK-HEADING) The TASK-PLAN-REGEXP is matched against the plan page (or pages if you are using planner-multi) for the task. If more than one TASK-PLAN-REGEXP matches, the first one in the list is used. All tasks that match the same TASK-PLAN-REGEXP will be grouped together. The order of the groups will match the order of TRUNK-SECTIONS-LIST. Tasks that do not match any entry in TRUNK-SECTIONS-LIST will be in a separate group at the end of the tasks section. If the sublist form of an entry is used, TRUNK-HEADING is a name for the outline heading to be inserted at the top of the trunk. If TRUNK-SECTIONS-LIST contains a mix of items in the regexp and sublist forms, when tasks are present that match a regexp form entry, but no tasks are present that match the most recent preceeding sublist form entry in the list, the heading from the sublist form entry will be inserted anyway. In use, it will become obvious why this is desirable." :type '(repeat (list :tag "Trunk rule" (choice :tag "Page regexp" (const "\\`[0-9][0-9][0-9][0-9][\\.\\-][0-9][0-9][\\.\\-][0-9][0-9]\\'" :tag "Day pages") (const "." :tag "All pages") (regexp :tag "Regexp")) (choice :tag "Completed tasks" (const :tag "With incomplete tasks" nil) (string :tag "Under section heading")) (repeat (choice (regexp :tag "Regexp") (list :tag "Regexp and section heading" (regexp :tag "Regexp") (string :tag "Section heading")))))) :group 'planner-trunk) (defcustom planner-trunk-tasks-before-hook nil "Functions to run before doing the trunk." :type 'hook :group 'planner-trunk) (defcustom planner-trunk-tasks-after-hook nil "Functions to run after the trunk is done." :type 'hook :group 'planner-trunk) ;;;_+ Internal variables and utility functions (defun planner-trunk-rule-page-regexp (rule) "Regular expression matching the page in RULE." (elt rule 0)) (defun planner-trunk-rule-completed-heading (rule) "Sub-heading for completed tasks in RULE." (elt rule 1)) (defun planner-trunk-rule-trunk-sections (rule) "Trunk section in RULE." (elt rule 2)) (defun planner-trunk-list-regexp (trunk) "Plan page regular expression for TRUNK." (if (listp trunk) (car trunk) trunk)) (defun planner-trunk-list-heading (trunk) "Heading for TRUNK." (if (listp trunk) (cadr trunk) nil)) (defun planner-trunk-task-plan-str (task-info) "Return plan string for TASK-INFO." (or (if (fboundp 'planner-multi-task-link-as-list) (mapconcat 'identity (planner-multi-task-link-as-list task-info) " ") (or (planner-task-link task-info) (planner-task-plan task-info))) "")) (defun planner-trunk-completed-p (task-info) "Return non-nil if TASK-INFO is a completed task." (or (equal (planner-task-status task-info) "X") (equal (planner-task-status task-info) "C"))) (defun planner-trunk-delete-all-blank-lines () "Delete all blank lines and insert one at the end." (goto-char (point-min)) (delete-blank-lines) (while (= (forward-line 1) 0) (delete-blank-lines)) (insert "\n")) (defun planner-trunk-delete-line-if-not-task () "Delete the current line if it is not a task." (if (planner-current-task-info) (not (equal (forward-line) 1)) (let ((bol (planner-line-beginning-position))) (let ((at-end (equal (forward-line) 1))) (beginning-of-line) (delete-region bol (point)) (not at-end))))) (defun planner-trunk-delete-non-task-lines () "Delete all lines that are not tasks. DANGEROUS." (goto-char (point-min)) (forward-line) ; Skip Tasks heading ;; (keep-lines "^#[A-C][0-9]*\\s-+.\\s-") or (while (planner-trunk-delete-line-if-not-task)) (insert "\n") (forward-line -1)) (defun planner-trunk-sort-tasks (rule) "Sort tasks by plan name according to the given RULE list." (let ((trunk-list (planner-trunk-rule-trunk-sections rule)) (completed-heading (planner-trunk-rule-completed-heading rule)) (task-info (planner-current-task-info))) (let ((trunk-count (length trunk-list)) (plan (planner-trunk-task-plan-str task-info)) (task-completed (planner-trunk-completed-p task-info))) (if (not plan) (+ 2 (if (and completed-heading task-completed) (* 2 trunk-count) trunk-count)) (catch 'done (let ((count 1)) (when (and completed-heading task-completed) (setq count (+ count trunk-count 2))) (mapc (lambda (trunk-entry) (let ((plan-regexp (planner-trunk-list-regexp trunk-entry))) (if (string-match plan-regexp plan) (throw 'done count) (setq count (1+ count))))) trunk-list) count)))))) (defun planner-trunk-ins-heading (completed-heading task-info heading) "Insert the task heading. If COMPLETED-HEADING is non-nil and TASK-INFO is a completed task, use COMPLETED-HEADING instead of HEADING." (when heading (insert "\n") (when (and completed-heading (planner-trunk-completed-p task-info)) (insert "*")) (insert "** " heading)) (insert "\n")) (defun planner-trunk-do-trunk-section (rule) "Really do the trunk. Adds new lines and optionally outline mode subheadings according to the trunk RULE. Point must be at the beginning of the section to trunk, typically either the beginning of the tasks section or the beginning of the completed subsection." (let ((not-done t) (completed-hdr (planner-trunk-rule-completed-heading rule)) ;; Following adds a dummy first entry to get rid of special ;; case to handle headings otherwise. It prevents anyone from ;; having a plan page named (_-), which I hope no-one wants to ;; do... (trunk-list (cons "^\\\\(_-\\\\)$" (planner-trunk-rule-trunk-sections rule))) (first-trunk (car (planner-trunk-rule-trunk-sections rule))) (ntasks 0)) (while (and trunk-list not-done) (let ((task-info (planner-current-task-info))) (when task-info (setq ntasks (1+ ntasks)) (let ((plan (planner-trunk-task-plan-str task-info)) (plan-regexp (planner-trunk-list-regexp (car trunk-list)))) (unless (string-match plan-regexp plan) (let ((hdr nil)) (while (and trunk-list (not (string-match plan-regexp plan))) (setq trunk-list (cdr trunk-list)) (setq plan-regexp (planner-trunk-list-regexp (car trunk-list))) (when (planner-trunk-list-heading (car trunk-list)) (setq hdr (planner-trunk-list-heading (car trunk-list))))) (when (planner-trunk-list-heading (car trunk-list)) (setq hdr (planner-trunk-list-heading (car trunk-list)))) (planner-trunk-ins-heading completed-hdr task-info hdr))))) (when (or (null trunk-list) (not (equal 0 (forward-line 1))) (and completed-hdr (not (planner-trunk-completed-p task-info)) (planner-trunk-completed-p (planner-current-task-info)))) (setq not-done nil)))) ntasks)) (defun planner-trunk-do-trunk (rule) "Really do the trunk following RULE." (goto-char (point-min)) (planner-trunk-do-trunk-section rule) (when (planner-trunk-rule-completed-heading rule) (while (let ((task-info (planner-current-task-info))) (and (not (planner-trunk-completed-p task-info)) (equal 0 (forward-line))))) (let ((start-completed-pos (point))) (when (> (planner-trunk-do-trunk-section rule) 0) (when (stringp (planner-trunk-rule-completed-heading rule)) (goto-char start-completed-pos) (insert "\n** " (planner-trunk-rule-completed-heading rule) "\n")))))) ;; user visible functions ;;;###autoload (defun planner-trunk-tasks (&optional force) "Trunk(group) tasks in the current page. Please refer the docstring of `planner-trunk-rule-list' for how it works. You may want to call this function before you sort tasks and/or after you create new tasks. If a prefix is given or FORCE is not nil, trunk completed tasks together with non-completed tasks not matter what the `planner-trunk-rule-list' said." (interactive "P") (let ((page-name (planner-page-name)) (rule-list planner-trunk-rule-list)) (let ((rule (catch 'done (while rule-list (if (string-match (caar rule-list) page-name) (throw 'done (car rule-list)) (setq rule-list (cdr rule-list)))) nil))) (if rule (save-excursion (save-restriction (run-hooks 'planner-trunk-tasks-before-hook) (when (planner-narrow-to-section 'tasks) (planner-trunk-delete-non-task-lines) (if force (setq rule (list (planner-trunk-rule-page-regexp rule) nil (planner-trunk-rule-trunk-sections rule)))) (let ((planner-sort-tasks-key-function (lambda () (planner-trunk-sort-tasks rule)))) (planner-sort-tasks)) (planner-trunk-do-trunk rule)) (run-hooks 'planner-trunk-tasks-after-hook))))))) (provide 'planner-trunk) ;;; planner-trunk.el ends here planner-el/planner-unix-mail.el000066400000000000000000000133131226462314700170050ustar00rootroot00000000000000;;; planner-unix-mail.el --- Unix mailbox support for Planner ;; Copyright (C) 2004, 2008 Frederik Fouvry ;; Author: Frederik Fouvry ;; Keywords: ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;;;_ + Usage ;; ;; Place planner-unix-mail.el in your load path and add this to your .emacs: ;; ;; (require 'planner-unix-mail) ;; ;; Unix mailbox URLs are of the form ;; ;; mail://PATH/TO/INBOX/message-id ;; ;; Annotations will be of the form ;; [[mail://PATH/TO/INBOX/E1AyTpt-0000JR-LU%40sacha.ateneo.edu][E-mail from Sacha Chua]] ;;; Contributors: ;; Yann Hodique fixed a typo and helped port this to Muse. ;;; Code: (require 'planner) ;;; Code: ;; This is (kind of) a combination of the "mid" and "file" (RFC 1738) ;; protocol. (defconst planner-unix-mail-protocol-name "mail") (defun planner-unix-mail-narrow-to-message () (save-match-data (let ((b (or (and (looking-at "^From ") (point)) (re-search-backward "^From "))) (e (progn (re-search-forward "\n\n\\(?:From \\|\\'\\)" nil 'point) (forward-line 0) (point)))) (narrow-to-region b e)))) ;; Encoding according to RFC 1738. (defun planner-url-encode (string &optional reserved) (save-match-data (let ((chars (split-string string "")) (newchars) (not-to-encode (concat "\\(?:[0-9A-Za-z]\\|[$_.+!*'(),-]" (if (and (stringp reserved) (not (string= reserved ""))) (concat "\\|" reserved) "") "\\)"))) (while chars (setq newchars (cons (if (string-match not-to-encode (car chars)) (car chars) (format "%%%x" (string-to-char (car chars)))) newchars) chars (cdr chars))) (eval (cons 'concat (nreverse newchars)))))) ;; Decoding according to RFC 1738 (defun planner-url-decode (string) (save-match-data (let* ((parts (split-string string "%")) (newparts) (ignore)) (unless (string-match "^%" string) (setq ignore (car parts) parts (cdr parts))) (while parts (when (string-match "^\\(..\\)" (car parts)) (setq newparts (cons (replace-match (char-to-string (string-to-number (match-string 1 (car parts)) 16)) nil t (car parts) 1) newparts))) (setq parts (cdr parts))) (eval (cons 'concat (append (when ignore (list ignore)) (nreverse newparts))))))) ;;;###autoload (defun planner-unix-mail-annotation-from-mail () "Return an annotation for the current message. This function can be added to `planner-annotation-functions'." (save-match-data ;; This test replaces the major-mode test. (when (save-excursion (save-restriction (widen) (and (goto-char (point-min)) (re-search-forward "\\`From " nil t) (goto-char (- (point-max) 3)) (re-search-forward "\n\n\\'" nil t)))) (save-excursion (save-restriction (planner-unix-mail-narrow-to-message) (planner-make-link (concat planner-unix-mail-protocol-name "://" (buffer-file-name) "/" ;; Format is defined on RFC 2111 ("/" is reserved, ;; but should not be used because of the presence ;; of the file path) (let* ((mid (mail-fetch-field "message-id"))) (if (stringp mid) (if (string-match "^<\\(.+\\)>$" mid) (planner-url-encode (match-string 1 mid) "[/]") (error "Mal-formed Message-Id header field encountered")) ;; From_ header could be used as a backup (error "No Message-Id header field found in this message")))) (if (and planner-ignored-from-addresses (string-match planner-ignored-from-addresses (mail-fetch-field "from")) (mail-fetch-field "to")) ; May be missing (concat "E-mail to " (planner-get-name-from-address (mail-fetch-field "to"))) (concat "E-mail from " (planner-get-name-from-address (mail-fetch-field "from")))) t)))))) ;;;###autoload (defun planner-unix-mail-browse-url (url) "If this is an UNIX-MAIL URL, jump to it." (save-match-data (when (string-match (concat "\\`" planner-unix-mail-protocol-name "://\\(.+\\)/\\(.+?\\)$") url) (let* ((message-id (planner-url-decode (match-string 2 url))) (file (match-string 1 url)) (point (save-excursion (save-window-excursion (find-file file) (save-restriction (widen) (goto-char (point-max)) (re-search-backward (concat "^Message-Id:[[:space:]]+<" (regexp-quote message-id) ">") nil t)))))) (if point (progn (find-file file) (goto-char point) (re-search-backward "^From ") (recenter 0)) (error "Message not found")))))) (planner-add-protocol (concat planner-unix-mail-protocol-name "://") 'planner-unix-mail-browse-url nil) (add-hook 'planner-annotation-functions 'planner-unix-mail-annotation-from-mail) (custom-add-option 'planner-annotation-functions 'planner-unix-mail-annotation-from-rmail) (planner-update-wiki-project) (provide 'planner-unix-mail) ;; ;; Local Variables: ;; indent-tabs-mode: t ;; tab-width: 8 ;; End: planner-el/planner-vm.el000066400000000000000000000103101226462314700155160ustar00rootroot00000000000000;;; planner-vm.el --- VM support for Planner, an organizer for Emacs ;; Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. ;;; Commentary: ;; ;;;_* Commentary ;;;_ + Package description ;; Emacs Lisp Archive Entry ;; Filename: planner.el ;; Keywords: hypermedia ;; Author: John Wiegley ;; Description: Use Emacs for life planning ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Compatibility: Emacs20, Emacs21, Emacs22, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_ + Usage ;; ;; Place planner-vm.el in your load path and add this to your .emacs: ;; ;; (require 'planner-vm) ;; ;; VM URLs are of the form ;; ;; vm://path/to/inbox/message-id ;; ;; Annotations will be of the form ;; [[vm://home/test/INBOX/][E-mail from Sacha Chua]] ;;;_ + Contributors ;; Jürgen Doser (email address unknown) contributed a patch to ;; properly open a vm message. ;; Greg Novak provided a message-id bugfix. ;; Fran Burstall provided a patch that turned on annotations in ;; vm-presentation-mode. (require 'planner) (require 'vm) ;;; Code: ;;;###autoload (defun planner-vm-annotation-from-mail () "Return an annotation for the current message. This function can be added to `planner-annotation-functions'." (save-excursion (save-restriction (when (eq major-mode 'vm-summary-mode) (vm-follow-summary-cursor) (set-buffer vm-mail-buffer)) (when (memq major-mode '(vm-mode vm-presentation-mode)) (let ((message (car vm-message-pointer))) (planner-make-link (concat "vm://" (buffer-file-name (marker-buffer (elt (vm-location-data-of (vm-real-message-of message)) 0))) "/" (vm-get-header-contents message "Message-ID")) (if (and planner-ignored-from-addresses (string-match planner-ignored-from-addresses (vm-get-header-contents message "From"))) (concat "E-mail to " (planner-get-name-from-address (vm-get-header-contents message "To"))) (concat "E-mail from " (planner-get-name-from-address (vm-get-header-contents message "From")))) t)))))) ;;;###autoload (defun planner-vm-browse-url (url) "If this is an VM URL, jump to it." (when (string-match "\\`vm://\\(.+\\)/\\([^/\n]+\\)$" url) (let ((message-id (match-string 2 url)) (inbox (match-string 1 url))) ; open the inbox read-only (vm inbox t) (let ((mp vm-message-list) (done nil)) ; search for matching message-id (while (and mp (not done)) (if (string= message-id (vm-get-header-contents (car mp) "Message-ID")) ; jump to the message and done (progn (vm-record-and-change-message-pointer vm-message-pointer mp) (vm-preview-current-message) (setq done t)) (setq mp (cdr mp)))) t)))) (planner-add-protocol "vm://" 'planner-vm-browse-url nil) (add-hook 'planner-annotation-functions 'planner-vm-annotation-from-mail) (custom-add-option 'planner-annotation-functions 'planner-vm-annotation-from-mail) (planner-update-wiki-project) (provide 'planner-vm) ;;;_* Local emacs vars. ;; Local variables: ;; allout-layout: (* 0 : ) ;; End: ;;; planner-vm.el ends here planner-el/planner-w3m.el000066400000000000000000000033651226462314700156160ustar00rootroot00000000000000;;; planner-w3m.el --- W3M integration for the Emacs Planner ;; Copyright (C) 2001, 2008 Free Software Foundation, Inc. ;; Author: John Wiegley ;; Keywords: planner, w3m ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; This module allows you to create tasks from a w3m buffer. ;;; Contributors: ;; John Sullivan provided a patch to check w3m-buffer-title. ;;; Code: (require 'w3m) (require 'planner) ;;;###autoload (defun planner-w3m-annotation-from-w3m () "If called from a w3m page, return an annotation. Suitable for use in `planner-annotation-functions'." (when (eq major-mode 'w3m-mode) (planner-make-link w3m-current-url (or w3m-current-title (w3m-buffer-title (current-buffer))) t))) (add-hook 'planner-annotation-functions 'planner-w3m-annotation-from-w3m) (custom-add-option 'planner-annotation-functions 'planner-w3m-annotation-from-w3m) (provide 'planner-w3m) ;;; planner-w3m.el ends here planner-el/planner-wl.el000066400000000000000000000074211226462314700155270ustar00rootroot00000000000000;;; planner-wl.el --- Wanderlust integration for the Emacs Planner ;; Copyright (C) 2004, 2008 Yvonne Thomson (yvonne AT netbrains DOT com DOT au) ;; Parts copyright (C) 2004, 2008 Angus Lees (gus AT inodes DOT org) ;; Parts copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. ;; Author: Yvonne Thomson (yvonne AT thewatch DOT net) ;; Keywords: planner, wanderlust, wl ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; Add ;; ;; (require 'planner-wl) ;; ;; to your .emacs or .wl. You will then be able to call ;; M-x planner-create-task-from-buffer from Wanderlust summary buffers ;; with the correct annotation. ;; To add keybindings to Wanderlust, call (from .emacs or .wl) ;; ;; (planner-wl-insinuate) ;; ;; This binds C-c C-t in summary buffers to `planner-create-task-from-buffer' ;; Note: ;; `planner-wl-annotation-from-wl' uses `wl-summary-from-function' (and ;; related options) rather than `planner-ignored-from-addresses' ;; URLs are of the form wl://foldername/msg-id ;;;_ + Contributors ;; Angus Lees (gus AT inodes DOT org) remade quite a bit of this file. ;; Jeremy Cowgar (jeremy AT cowgar DOT com) updated this to work with ;; Wanderlust 2.12.0. ;;; Code: (require 'planner) (require 'wl) (require 'wl-summary) ;;;###autoload (defun planner-wl-insinuate () "Hook Planner into Wanderlust. Add special planner keybindings to`wl-summary-mode-map'. From the Wanderlust Summary view, you can type C-c C-t to create a task." (define-key wl-summary-mode-map (kbd "C-c C-t") 'planner-create-task-from-buffer)) ;;;###autoload (defun planner-wl-annotation-from-wl () "If called from wl, return an annotation. Suitable for use in `planner-annotation-functions'." (when (equal major-mode 'wl-summary-mode) (let* ((msgnum (wl-summary-message-number)) (msg-id (elmo-message-field wl-summary-buffer-elmo-folder msgnum 'message-id)) (wl-message-entity (if (fboundp 'elmo-message-entity) (elmo-message-entity wl-summary-buffer-elmo-folder msgnum) (elmo-msgdb-overview-get-entity msgnum (wl-summary-buffer-msgdb))))) (planner-make-link (concat "wl://" wl-summary-buffer-folder-name "/" msg-id) (concat "E-Mail " (wl-summary-line-from)) t)))) ;;;###autoload (defun planner-wl-browse-url (url) "If this is a Wanderlust URL, jump to it." (when (string-match "\\`wl:/*\\(.+\\)/\\(.+\\)" url) (let ((group (match-string 1 url)) (article (match-string 2 url))) (wl-summary-goto-folder-subr group 'no-sync t nil t) (wl-summary-jump-to-msg-by-message-id article) (wl-summary-redisplay) ;; force a non-nil return value t))) (planner-add-protocol "wl:/*" 'planner-wl-browse-url nil) (custom-add-option 'planner-annotation-functions 'planner-wl-annotation-from-wl) (add-hook 'planner-annotation-functions 'planner-wl-annotation-from-wl) (provide 'planner-wl) ;;; planner-wl.el ends here planner-el/planner-xtla.el000066400000000000000000000137741226462314700160650ustar00rootroot00000000000000;;; planner-xtla.el --- Xtla integration for the Emacs Planner ;; Copyright (C) 2005, 2008 Free Software Foundation, Inc. ;; Parts copyright (C) 2005, 2008 Yann Hodique (hodique AT lifl DOT fr) ;; Author: Stefan Reichör ;; Keywords: planner, xtla ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_ + Commentary: ;; This file allows you to refer to your tla changesets easily from within ;; a planner page. ;; ;; Example: ;; [[xtla://miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-19][patch-19]] ;; can be browsed easily via xtla ;;; Contributors: ;; Yann Hodique helped port this to Muse. ;;; Code: (require 'planner) (require 'xtla) (defgroup planner-xtla nil "Planner options for the xtla integration." :prefix "planner-xtla-" :group 'planner) (defcustom planner-xtla-log-edit-include-files-flag t "Non-nil means include a list of committed files in the note." :type 'boolean :group 'planner-xtla) (defcustom planner-xtla-log-edit-notice-commit-function nil "Function that should return non-nil if this commit should be noted. The function will be run in the log buffer." :type '(choice (const :tag "Always note commits" t) function) :group 'planner-xtla) (defcustom planner-xtla-url-transform-alist nil "List of associations between a branch name with a base url. For example : '(\"hodique@lifl.fr--2005\" . \"http://www.lifl.fr/~hodique/archives/2005\"). This overrides the url given by `tla--archive-tree'. Useful when using a mirror." :type '(repeat (cons string string)) :group 'planner-xtla) ;;;###autoload (defun planner-annotation-from-xtla () "If called from a xtla buffer, return an annotation. Suitable for use in `planner-annotation-functions'." (cond ((eq major-mode 'tla-revision-list-mode) (planner-make-link (concat "xtla://" (cadr (tla--get-revision-info-at-point))) (cadr (tla--get-revision-info-at-point)))))) ;;;###autoload (defun planner-xtla-browse-url (url) "If this is a xtla url, handle it." (when (string-match "\\`xtla:/?/?\\(.+\\)" url) (tla-get-changeset (match-string 1 url) t) t)) ;;;###autoload (defun planner-xtla-log-edit-add-note () "Provide `planner-log-edit'-like functionality for xtla. This function is automatically called by `tla-commit-hook'. See also `planner-xtla-log-edit-notice-commit-function'." (interactive) (when (if (functionp planner-xtla-log-edit-notice-commit-function) (funcall planner-xtla-log-edit-notice-commit-function) planner-xtla-log-edit-notice-commit-function) (let ((arch-revision) (planner-xtla-link) (committed-files)) ;; assume we are in the *tla-buffer* after the commit (goto-char (point-min)) (re-search-forward "^\\* committed ") (setq arch-revision (buffer-substring-no-properties (point) (planner-line-end-position))) (setq committed-files (buffer-substring-no-properties (point-min) (planner-line-beginning-position))) (setq planner-xtla-link (planner-make-link (concat "xtla://" arch-revision) arch-revision)) (save-window-excursion (planner-create-note nil) (insert "Commit") (insert (concat " " planner-xtla-link)) (newline) (when planner-xtla-log-edit-include-files-flag (insert "Files:\n") (insert committed-files) (newline)) (insert (replace-regexp-in-string "^\\*" " *" tla-last-commit-message)))))) (defun planner-xtla-url-transform (target &rest ignored) "Transforms a xtla link into a http link to a public location. The association is first searched in `planner-xtla-url-transform-alist', and then in `tla--archive-tree'" (tla--archive-tree-build-archives t) (let ((reg (concat "\\`xtla:/?/?\\(\\(?:" (mapconcat 'car tla--archive-tree "\\|") "\\)/\\(?:.*\\)\\)$"))) (save-match-data (if (string-match reg target) (let* ((elts (tla--name-split (match-string 1 target))) (subst (or (cdr (assoc (car elts) planner-xtla-url-transform-alist)) (car (cadr (assoc (car elts) tla--archive-tree)))))) (when (nth 1 elts) (setq subst (concat subst "/" (nth 1 elts))) (when (nth 2 elts) (setq subst (concat subst "/" (nth 1 elts) "--" (nth 2 elts))) (when (nth 3 elts) (setq subst (concat subst "/" (nth 1 elts) "--" (nth 2 elts) "--" (nth 3 elts))) (when (nth 4 elts) (setq subst (concat subst "/" (nth 4 elts)))))))) target)))) (add-to-list 'muse-publish-url-transforms 'planner-xtla-url-transform) (add-hook 'tla-commit-done-hook 'planner-xtla-log-edit-add-note) (planner-add-protocol "xtla:/?/?" 'planner-xtla-browse-url 'planner-xtla-url-transform) (add-hook 'planner-annotation-functions 'planner-annotation-from-xtla) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-xtla) (provide 'planner-xtla) ;;; planner-xtla.el ends here planner-el/planner-zoom.el000066400000000000000000000734431226462314700161000ustar00rootroot00000000000000;;; planner-zoom.el --- navigate Planner pages ;; Copyright (C) 2006, 2008 Gregory Novak ;; Parts copyright (C) 2006, 2008 Free Software Foundation, Inc. ;; Author: Gregory Novak ;; Date: 10-Mar-2006 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; One of the things I like about using Planner is that it gets me ;; into the habit of, at the beginning of the day, deciding what I'm ;; going to do and, at the end of the day, evaluating whether or not I ;; achieved my goals. I'd like to do this same thing at the week ;; level, the month level, the quarter level, and the year level. ;; This way each time period breaks down into 3-4 smaller time ;; periods, and I can keep an eye on larger, longer-term goals. (I've ;; posted one or two messages about this before). ;; ;; To this end, I've put together a little code that lets you skip ;; around on pages that correspond to the different time intervals. ;; When I'm looking at how I did over the past month, I want an easy ;; way to look at how I did for the weeks of that month. Typing out ;; all the page names is tedious and time consuming, so I've created ;; four functions zoom-iup (for interactive-up), zoom-idown, ;; zoom-inext, and zoom-iprev (which I bind to Shift-up, Shift-down, ;; etc). ;; ;; The naming convention for pages is: ;; year - "2006.Year" ;; quarter - "2006.Quarter2" ;; month - "2006.January" ;; week - "2006.January.Week3" ;; day - "2006.01.02" ;; (this can be changed by changing zoom-regexps) ;; ;; So typically I would look at the page named "2006.January" and then ;; hit 'C-u S-down' which shows me 2006.January.Week1 in the other ;; buffer. Then I can hit S-left and S-right to look at ;; 2006.January.Week2, 2006.January.Week3, etc. ;; ;; I determine the month to which each week belongs by the month which ;; contains the zoom-first-day-of-week'th day of that week. Zero is ;; Sunday, one is Monday, etc. Therefore the March 1, 2006, would ;; typically be fall into "2006.February.Week4" ;;; Contributors: ;;; Code: (require 'planner) (eval-when-compile (require 'cl)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Config (defvar planner-zoom-first-day-of-week 1 "What day should be considered the first of the week. Zero for Sunday, one for Monday, etc") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Guts (defvar planner-zoom-months '(("January" . 1) ("February" . 2) ("March" . 3) ("April" . 4) ("May" . 5) ("June" . 6) ("July" . 7) ("August" . 8) ("September" . 9) ("October" . 10) ("November" . 11) ("December" . 12) ("Month" . 13)) ; Extra invalid value "Alist associating month names with numbers.") (defvar planner-zoom-month-regexp (concat "\\(" (mapconcat #'car planner-zoom-months "\\|") "\\)") "Regexp matching any month name given in planner-planner-zoom-months.") (defvar planner-zoom-regexps (list '("^\\([0-9]\\{4\\}\\).Year$" . year) ; (year) '("^\\([0-9]\\{4\\}\\).Quarter\\([0-5]\\)$" . quarter) ; (year, quarter) (cons (concat "^\\([0-9]\\{4\\}\\)." planner-zoom-month-regexp "$") 'month) ; (year, month) (cons (concat "^\\([0-9]\\{4\\}\\)." planner-zoom-month-regexp ".Week\\([0-6]\\)$") 'week); year, month, week '("^\\([0-9]\\{4\\}\\).\\([0-9]\\{1,2\\}\\).\\([0-9]\\{1,2\\}\\)$" . day)) ; year, month, day "Alist of regexps that match names of years, quarters, months, weeks, and days.") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Heavy lifting functions (defun planner-zoom-parse-to-strings (name &optional type) "Parse a string NAME, into a period of time given by `planner-zoom-regexps'. If TYPE is given, it is a symbol specifying the type of time-period which NAME should be parsed as (one of 'day, 'week, 'month, 'quarter, or 'year. Return a four element list consisting of the type of time period and then a list of strings containing the subexpressions matched by the successful regexp. Eg, \(planner-zoom-parse-to-strings \"2006.Year\") returns \(year \"2006\" nil nil) and \(planner-zoom-parse-to-strings \"2006.January.Week1\") returns \(week \"2006\" \"January\" \"1\")" (setq type (or type (assoc-default name planner-zoom-regexps 'string-match))) ;; Make sure the match data is for the right search (unless (string-match (car (rassoc type planner-zoom-regexps)) name) (error "planner-zoom: Couldn't parse name")) (cons type (list (match-string 1 name) (match-string 2 name) (match-string 3 name)))) (defun planner-zoom-parse (&rest args) "Parse a string NAME, into a period of time given by `planner-zoom-regexps'. If TYPE is given, it is a symbol specifying the type of time-period which NAME should be parsed as (one of 'day, 'week, 'month, 'quarter, or 'year. Return a four element list consisting of the type of time period and then numerical representations of the subexpressions matched by the successful regexp. Eg, \(planner-zoom-parse \"2006.Year\") returns (year 2006 nil nil) and (planner-zoom-parse \"2006.January.Week1\") returns (week 2006 1 1)." (let* ((result (apply 'planner-zoom-parse-to-strings args)) (type (car result)) (strings (cdr result)) numbers) (dotimes (i (length strings)) (setq numbers (cons (when (not (null (nth i strings))) (if (or (and (eq type 'month) (= i 1)) (and (eq type 'week) (= i 1))) (cdr (assoc (nth i strings) planner-zoom-months)) (string-to-number (nth i strings)))) numbers))) (cons type (nreverse numbers)))) (defun planner-zoom-string (type &rest changes) "Convert time-range info into a string name. You can specify numerical values or strings. So, \(planner-zoom-string 'year 2006) -> \"2006.Year\" \(planner-zoom-string 'year \"2006\") -> \"2006.Year\" \(planner-zoom-string 'week 2006 \"February\" 3) -> \"2006.February.Week3\" \(planner-zoom-string 'week 2006 2 3) -> \"2006.February.Week3\"" ;; use a template (let ((name (cdr (assoc type '((year . "1000.Year") (quarter . "1000.Quarter5") (month . "1000.Month") (week . "1000.Month.Week6") (day . "1000.99.99")))))) ;; Make sure changes are strings (let (result) (dotimes (i (length changes)) (setq result (cons (if (not (numberp (nth i changes))) (nth i changes) (if (or (and (eq type 'month) (= i 1)) (and (eq type 'week) (= i 1))) (car (rassoc (nth 1 changes) planner-zoom-months)) (number-to-string (nth i changes)))) result))) (setq changes (nreverse result))) ;; Special handling for days + months in 'day strings: make sure ;; they're two digits (when (eq type 'day) (setq changes (mapcar (lambda (x) (if (= (length x) 1) (concat "0" x) x)) changes))) (dotimes (i (length changes)) (planner-zoom-parse name type) ; make sure match data is ; correct each time (setq name (replace-match (nth i changes) t t name (1+ i)))) name)) (defun planner-zoom-range (min max) "Return a list of numbers from MIN to MAX." (let ((lst nil)) (while (<= min max) (setq lst (cons max lst)) (setq max (1- max))) lst)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interactive (add-hook 'planner-mode-hook (lambda () (local-set-key (kbd "") 'planner-zoom-iup) (local-set-key (kbd "") 'planner-zoom-idown) (local-set-key (kbd "") 'planner-zoom-iprev) (local-set-key (kbd "") 'planner-zoom-inext))) (defun planner-zoom-iup (name other-window) "Move to the next higher level in the hierarchy." (interactive (list (planner-page-name) current-prefix-arg)) (when other-window (other-window 1)) (planner-find-file (planner-zoom-up name)) (when other-window (other-window 1))) (defun planner-zoom-idown (name other-window) "Move to the next lower level in the hierarchy. If the current date is within the higher-level time range, zoom to the lower level time range that also contains today. Otherwise, just go to the first lower-level time range." (interactive (list (planner-page-name) current-prefix-arg)) (when other-window (other-window 1)) (planner-find-file (planner-zoom-down name)) (when other-window (other-window 1))) (defun planner-zoom-inext (name num other-window) "Move to the next time range at the same level in the hierarchy. With a numeric prefix arg, move by that number of time ranges. With a non-numeric prefix arg, show the desired page in the other window." (interactive (list (planner-page-name) (if (numberp current-prefix-arg) current-prefix-arg 1) (consp current-prefix-arg))) (when other-window (other-window 1)) (planner-find-file (planner-zoom-next name num)) (when other-window (other-window 1))) (defun planner-zoom-iprev (name num other-window) "Move to the previous time range at the same level in the hierarchy. With a numeric prefix arg, move by that number of time ranges. With a non-numeric prefix arg, show the desired page in the other window." (interactive (list (planner-page-name) (if (numberp current-prefix-arg) current-prefix-arg 1) (consp current-prefix-arg))) (when other-window (other-window 1)) (planner-find-file (planner-zoom-next name (- num))) (when other-window (other-window 1))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Non-period-specific stuff (defun planner-zoom-contains (name &optional today) "Test if TODAY is contained within the time period specified by string NAME. If TODAY is not given, use the current date" (setq today (or today (gsn/calendar-today-absolute))) (and (<= (planner-zoom-beg name) today) (>= (planner-zoom-end name) today))) (defun planner-zoom-beg (name) "Return the absolute date of the beginning of the time period specified by string NAME." (funcall ;; This is basically do-it-yourself object orientation. Times are ;; lists where the first element is the type and the other elements ;; are type-specific information. This function call dispatches on ;; the type, so it's basically a method call on a time range. (cdr (assoc (car (planner-zoom-parse name)) '((year . planner-zoom-year-beg) (quarter . planner-zoom-quarter-beg) (month . planner-zoom-month-beg) (week . planner-zoom-week-beg) (day . planner-zoom-day-beg)))) name)) (defun planner-zoom-end (name) "Return the absolute date of the end of the time period specified by string NAME." (funcall ;; See planner-zoom-beg comments (cdr (assoc (car (planner-zoom-parse name)) '((year . planner-zoom-year-end) (quarter . planner-zoom-quarter-end) (month . planner-zoom-month-end) (week . planner-zoom-week-end) (day . planner-zoom-day-end)))) name)) (defun planner-zoom-up (name) "For time range given by string NAME, return a string representiang the next higher enclosing time range in the heirarchy." (funcall ;; See planner-zoom-beg comments (cdr (assoc (car (planner-zoom-parse name)) '((year . planner-zoom-up-year) (quarter . planner-zoom-up-quarter) (month . planner-zoom-up-month) (week . planner-zoom-up-week) (day . planner-zoom-up-day)))) name)) (defun planner-zoom-down (name) "For time range given by string NAME, return a string representiang the next lower time range in the heirarchy. If the current date is within the higher-level time range, choose the lower-level time range that also includes the current date. Otherwise, just retturn the first lower-level time range" (funcall ;; See planner-zoom-beg comments (cdr (assoc (car (planner-zoom-parse name)) '((year . planner-zoom-down-year) (quarter . planner-zoom-down-quarter) (month . planner-zoom-down-month) (week . planner-zoom-down-week) (day . planner-zoom-down-day)))) name)) (defun planner-zoom-next (name num) "For time range given by string NAME, return a string representiang the next time range at the same level in the heirarchy." (funcall ;; See planner-zoom-beg comments (cdr (assoc (car (planner-zoom-parse name)) '((year . planner-zoom-next-year) (quarter . planner-zoom-next-quarter) (month . planner-zoom-next-month) (week . planner-zoom-next-week) (day . planner-zoom-next-day)))) name num)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Year (defun planner-zoom-year-beg (name) "Return the absolute date of the beginning of the year specified by string NAME." (multiple-value-bind (type year) (planner-zoom-parse name 'year) (calendar-absolute-from-gregorian (list 1 1 year)))) (defun planner-zoom-year-end (name) "Return the absolute date of the end of the year specified by string NAME." (multiple-value-bind (type year) (planner-zoom-parse name 'year) (calendar-absolute-from-gregorian (list 12 31 year)))) (defun planner-zoom-up-year (name) "Error: there's nothing above year in the heirarchy." nil) (defun planner-zoom-next-year (name num) "Return a string NUM years after the one given by string NAME." (multiple-value-bind (type year) (planner-zoom-parse name 'year) (planner-zoom-string 'year (+ num year)))) (defun planner-zoom-down-year (name &optional today) "If the absolute date TODAY is within the year specified by NAME, return a string for the quarter that also contains TODAY. Otherwise, return the a string for the first quarter in the year. If TODAY is not given, use the current date." (multiple-value-bind (junk year) (planner-zoom-parse name 'year) (if (not (planner-zoom-contains name today)) (planner-zoom-string 'quarter year 1) (car (planner-remove-if-not (lambda (p) (planner-zoom-contains p today)) (mapcar (lambda (n) (planner-zoom-string 'quarter year n)) (planner-zoom-range 1 4))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Quarter (defun planner-zoom-up-quarter (name) "Return a string for the year containing the quarter specified by string NAME." (multiple-value-bind (type year quarter) (planner-zoom-parse name 'quarter) (planner-zoom-string 'year year))) (defun planner-zoom-quarter-beg (name) "Return the absolute date of the first day of the quarter given by string NAME." (multiple-value-bind (type year quarter) (planner-zoom-parse name 'quarter) (calendar-absolute-from-gregorian (list (1+ (* 3 (1- quarter))) 1 year)))) (defun planner-zoom-quarter-end (name) "Return the absolute date of the last day of the quarter given by string NAME" (multiple-value-bind (type year quarter) (planner-zoom-parse name 'quarter) (cond ((= 1 quarter) (calendar-absolute-from-gregorian (list 3 31 year))) ((= 2 quarter) (calendar-absolute-from-gregorian (list 6 30 year))) ((= 3 quarter) (calendar-absolute-from-gregorian (list 9 30 year))) ((= 4 quarter) (calendar-absolute-from-gregorian (list 12 31 year)))))) (defun planner-zoom-next-quarter (name num) "Return a string for the name of the NUMth quarter after the one given by string NAME." (multiple-value-bind (type year quarter) (planner-zoom-parse name 'quarter) (let ((new-year (+ year (floor (/ (1- (float (+ quarter num))) 4)))) (new-quarter (1+ (mod (1- (+ quarter num)) 4)))) (planner-zoom-string 'quarter new-year new-quarter)))) (defun planner-zoom-down-quarter (name &optional today) "If the absolute TODAY is within the quarter given by string NAME, return a string for the month that also contains TODAY. Otherwise, return a string for the first month in the quarter. If TODAY is not given, use the current date." (multiple-value-bind (type year quarter) (planner-zoom-parse name 'quarter) (if (not (planner-zoom-contains name today)) (planner-zoom-string 'month year (1+ (* (1- quarter) 3))) ;; inefficient, but correct, to just include all months in the ;; test since we know that the current quarter contains today, ;; therefore some month in another quarter _cannot_ contain ;; today (car (planner-remove-if-not (lambda (p) (planner-zoom-contains p today)) (mapcar (lambda (n) (planner-zoom-string 'month year n)) (planner-zoom-range 1 12))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Month (defun planner-zoom-month-beg (name) "Return the absolute date of the first day of the month given by the string NAME." (multiple-value-bind (type year month) (planner-zoom-parse name 'month) (calendar-absolute-from-gregorian (list month 1 year)))) (defun planner-zoom-month-end (name) "Return the absolute date of the last day of the month given by the string NAME." (multiple-value-bind (type year month) (planner-zoom-parse name 'month) (calendar-absolute-from-gregorian (list month (calendar-last-day-of-month month year) year)))) (defun planner-zoom-up-month (name) "Return a string for the quarter containing the month given by string NAME." (multiple-value-bind (type year month) (planner-zoom-parse name) (let ((quarter (1+ (/ (1- month) 3)))) (planner-zoom-string 'quarter year quarter)))) (defun planner-zoom-next-month (name num) "Return a string for the NUMth month after the one given by the string NAME." (multiple-value-bind (type year month) (planner-zoom-parse name 'month) (let ((new-year (+ year (floor (/ (1- (float (+ month num))) 12)))) (new-month (1+ (mod (1- (+ month num)) 12)))) (planner-zoom-string 'month new-year new-month)))) (defun planner-zoom-down-month (name &optional today) "If the absolute date TODAY is within the month given by the string NAME, return a string for the week that also contains TODAY. Otherwise, return a string for the first week in the month. If TODAY is not given, use the current date." (multiple-value-bind (type year month) (planner-zoom-parse name 'month) (if (not (planner-zoom-contains name today)) (planner-zoom-string 'week year month 1) (car (planner-remove-if-not (lambda (p) (planner-zoom-contains p today)) (mapcar (lambda (n) (planner-zoom-string 'week year month n)) (planner-zoom-range 1 5))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Week (defun planner-zoom-week-beg (name) "Return the absolute date of the first day of the week given by string NAME." (multiple-value-bind (type year month week) (planner-zoom-parse name 'week) (calendar-absolute-from-gregorian (calendar-nth-named-day week planner-zoom-first-day-of-week month year)))) (defun planner-zoom-week-end (name) "Return the absolute date of the last day of the week given by string NAME." (+ 6 (planner-zoom-week-beg name))) (defun planner-zoom-up-week (name) "Return a string for the month containing the week given by string NAME." (multiple-value-bind (type year month week) (planner-zoom-parse name 'week) (planner-zoom-string 'month year month))) (defun planner-zoom-next-week (name num) "Return a string for the NUMth week after the one specified by the string NAME." (multiple-value-bind (type year month week) (planner-zoom-parse name 'week) ;; New week <= 0 leads to problems with nth-named-day... try to fix them? (let* ((new-week (if (> (+ week num) 0) (+ week num) (1- (+ week num)))) (new-date (calendar-nth-named-day new-week planner-zoom-first-day-of-week month year 1)) (new-year (extract-calendar-year new-date)) (new-month (extract-calendar-month new-date)) (new-day (extract-calendar-day new-date)) (first-date (calendar-nth-named-day 1 planner-zoom-first-day-of-week new-month new-year 1)) (first-day (extract-calendar-day first-date)) (new-week (1+ (/ (- new-day first-day) 7)))) (planner-zoom-string 'week new-year new-month new-week)))) (defun planner-zoom-down-week (name &optional today) "If the absolute date TODAY is within the week specified by string NAME, return a string for TODAY. Otherwise, return the first day in the week. If TODAY is not given, use the current date." (setq today (or today (gsn/calendar-today-absolute))) (multiple-value-bind (type year month week) (planner-zoom-parse name 'week) (if (not (planner-zoom-contains name today)) (planner-zoom-string 'day year month (extract-calendar-day (calendar-nth-named-day week planner-zoom-first-day-of-week month year))) (let* ((today (calendar-gregorian-from-absolute today)) (year (extract-calendar-year today)) (month (extract-calendar-month today)) (day (extract-calendar-day today))) (planner-zoom-string 'day year month day))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Day (defun planner-zoom-day-beg (name) "Return the absolute date of the day given by the string NAME." (multiple-value-bind (type year month day) (planner-zoom-parse name 'day) (calendar-absolute-from-gregorian (list month day year)))) (defun planner-zoom-day-end (name) "Return the absolute date of the day given by the string NAME." (planner-zoom-day-beg name)) (defun planner-zoom-up-day (name) "Return a string for the week that contains the day given by the string NAME." (multiple-value-bind (type year month day) (planner-zoom-parse name 'day) (let* ((first-date (calendar-nth-named-day 1 planner-zoom-first-day-of-week month year)) (first-day (extract-calendar-day first-date)) (week (1+ (/ (- day first-day) 7)))) (planner-zoom-string 'week year month week)))) (defun planner-zoom-next-day (name num) "Return the NUMth day after the one given by the string NAME." (let ((new-date (calendar-gregorian-from-absolute (+ (planner-zoom-day-beg name) num)))) (planner-zoom-string 'day (extract-calendar-year new-date) (extract-calendar-month new-date) (extract-calendar-day new-date)))) (defun planner-zoom-down-day (name) nil) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar planner-zoom-tests '((planner-zoom-parse-to-strings ("2006.Year") (year "2006" nil nil)) (planner-zoom-parse-to-strings ("2006.January") (month "2006" "January" nil)) (planner-zoom-parse-to-strings ("2006.Quarter1") (quarter "2006" "1" nil)) (planner-zoom-parse-to-strings ("2006.January.Week1") (week "2006" "January" "1")) (planner-zoom-parse-to-strings ("2006.01.03") (day "2006" "01" "03")) (planner-zoom-parse ("2006.Year") (year 2006 nil nil)) (planner-zoom-parse ("2006.January") (month 2006 1 nil)) (planner-zoom-parse ("2006.Quarter1") (quarter 2006 1 nil)) (planner-zoom-parse ("2006.January.Week1") (week 2006 1 1)) (planner-zoom-parse ("2006.01.03") (day 2006 1 3)) (planner-zoom-string (year 2007) "2007.Year") (planner-zoom-string (year "2007") "2007.Year") (planner-zoom-string (quarter 2007 2) "2007.Quarter2") (planner-zoom-string (quarter "2007" "2") "2007.Quarter2") (planner-zoom-string (month 2007 2) "2007.February") (planner-zoom-string (month "2007" "February") "2007.February") (planner-zoom-string (week 2007 2 2) "2007.February.Week2") (planner-zoom-string (week "2007" "February" "2") "2007.February.Week2") (planner-zoom-string (day 2007 2 2) "2007.02.02") (planner-zoom-string (day "2007" "2" "2") "2007.02.02") (planner-zoom-contains ("2006.Year" 732311) nil) (planner-zoom-contains ("2006.Year" 732312) t) (planner-zoom-contains ("2006.Year" 732463) t) (planner-zoom-contains ("2006.Year" 732676) t) (planner-zoom-contains ("2006.Year" 732677) nil) (planner-zoom-year-beg ("2006.Year") 732312) (planner-zoom-quarter-beg ("2006.Quarter1") 732312) (planner-zoom-quarter-beg ("2006.Quarter2") 732402) (planner-zoom-quarter-beg ("2006.Quarter3") 732493) (planner-zoom-quarter-beg ("2006.Quarter4") 732585) (planner-zoom-month-beg ("2006.January") 732312) (planner-zoom-week-beg ("2006.January.Week1") 732313) (planner-zoom-week-beg ("2006.January.Week2") 732320) (planner-zoom-week-beg ("2006.January.Week3") 732327) (planner-zoom-week-beg ("2006.January.Week4") 732334) (planner-zoom-week-beg ("2006.January.Week5") 732341) (planner-zoom-week-beg ("2006.January.Week6") 732348) (planner-zoom-day-beg ("2006.02.03") 732345) (planner-zoom-year-end ("2006.Year") 732676) (planner-zoom-quarter-end ("2006.Quarter1") 732401) (planner-zoom-quarter-end ("2006.Quarter2") 732492) (planner-zoom-quarter-end ("2006.Quarter3") 732584) (planner-zoom-quarter-end ("2006.Quarter4") 732676) (planner-zoom-month-end ("2006.January") 732342) (planner-zoom-week-end ("2006.January.Week1") 732319) (planner-zoom-week-end ("2006.January.Week2") 732326) (planner-zoom-week-end ("2006.January.Week3") 732333) (planner-zoom-week-end ("2006.January.Week4") 732340) (planner-zoom-week-end ("2006.January.Week5") 732347) (planner-zoom-week-end ("2006.January.Week6") 732354) (planner-zoom-day-end ("2006.01.01") 732312) (planner-zoom-next-year ("2006.Year" 2) "2008.Year") (planner-zoom-next-year ("2006.Year" -2) "2004.Year") (planner-zoom-next-year ("2006.Year" 0) "2006.Year") (planner-zoom-next-quarter ("2006.Quarter2" 5) "2007.Quarter3") (planner-zoom-next-quarter ("2006.Quarter2" -5) "2005.Quarter1") (planner-zoom-next-quarter ("2006.Quarter2" 0) "2006.Quarter2") (planner-zoom-next-month ("2006.June" 13) "2007.July") (planner-zoom-next-month ("2006.June" -13) "2005.May") (planner-zoom-next-month ("2006.June" 0) "2006.June") (planner-zoom-next-week ("2006.April.Week2" 3) "2006.May.Week1") (planner-zoom-next-week ("2006.April.Week2" -2) "2006.March.Week4") (planner-zoom-next-week ("2006.April.Week2" 0) "2006.April.Week2") (planner-zoom-next-day ("2006.04.03" -7) "2006.03.27") (planner-zoom-next-day ("2006.04.03" -1) "2006.04.02") (planner-zoom-next-day ("2006.04.03" 0) "2006.04.03") (planner-zoom-next-day ("2006.04.03" 1) "2006.04.04") (planner-zoom-next-day ("2006.04.03" 28) "2006.05.01") (planner-zoom-up-quarter ("2006.Quarter1") "2006.Year") (planner-zoom-up-month ("2006.April") "2006.Quarter2") (planner-zoom-up-week ("2006.April.Week1") "2006.April") (planner-zoom-up-day ("2006.04.10") "2006.April.Week2") ;(calendar-absolute-from-gregorian (4 30 2006) 732431) ;(calendar-absolute-from-gregorian (4 30 2005) 732066) ;; April 30th, 2006: Should zoom down to Q2, Month 4, Week 4, day 4.30.2006 (planner-zoom-down-year ("2006.Year" 732431) "2006.Quarter2") (planner-zoom-down-quarter ("2006.Quarter2" 732431) "2006.April") (planner-zoom-down-month ("2006.April" 732431) "2006.April.Week4") (planner-zoom-down-week ("2006.April.Week4" 732431) "2006.04.30") ;; April 30th, 2005: Should zoom down to Q1, January, Week 1, 1.1.2006 (planner-zoom-down-year ("2006.Year" 732066) "2006.Quarter1") (planner-zoom-down-quarter ("2006.Quarter1" 732066) "2006.January") (planner-zoom-down-month ("2006.January" 732066) "2006.January.Week1") (planner-zoom-down-week ("2006.January.Week1" 732066) "2006.01.02")) "A list of lists of the form (function-name function-arguments desired-result) which is used to test the functions in the zoom package.") (defun planner-zoom-test () "Run all the tests in planner-zoom-tests." (dolist (test planner-zoom-tests) (let* ((fn (first test)) (fn-args (second test)) (desired-result (third test)) (result (apply fn fn-args))) (when (not (equal desired-result result)) (error "Failed test!")))) t) (defun gsn/calendar-today-gregorian () (multiple-value-bind (junk junk junk day month year) (decode-time) (list month day year))) (defun gsn/calendar-today-absolute () (calendar-absolute-from-gregorian (gsn/calendar-today-gregorian))) (provide 'planner-zoom) ;;; planner-zoom.el ends here planner-el/planner.el000066400000000000000000005214231226462314700151120ustar00rootroot00000000000000;;; planner.el --- The Emacs Planner ;;; Commentary: ;;;_* Commentary ;;;_ + Package description ;; Copyright (C) 2001, 2003, 2004, 2005, ;; 2006, 2007, 2008, 2010 Free Software Foundation, Inc. ;; Parts copyright (C) 2004, 2008 David D. Smith (davidsmith AT acm DOT org) ;; Parts copyright (C) 2004, 2008 Yvonne Thomson (yvonne AT netbrains DOT com DOT au) ;; Parts copyright (C) 2004, 2008 Maciej Kalisak (mac AT cs DOT toronto DOT edu) ;; Parts copyright (C) 2004, 2008 Chris Parsons (chris.p AT rsons.org) ;; Parts copyright (C) 2004, 2008 Dirk Bernhardt (nospam AT krid.de) ;; Parts copyright (C) 2005, 2008 Dryice Dong Liu ;; Parts copyright (C) 2005, 2008 Angus Lees (gus AT debian.org) ;; Parts copyright (C) 2005, 2008 Sergey Vlasov (vsu AT altlinux.ru) ;; Parts copyright (C) 2005, 2008 Yann Hodique (hodique AT lifl DOT fr) ;; Parts copyright (C) 2005, 2008 Peter K. Lee ;; Parts copyright (C) 2006, 2007 Software Freedom Law Center ;; Emacs Lisp Archive Entry ;; Filename: planner.el ;; Version: 3.42 ;; Keywords: hypermedia ;; Author: John Wiegley ;; Maintainer: John Sullivan ;; Description: Use Emacs for life planning ;; URL: http://www.wjsullivan.net/PlannerMode.html ;; Bugs: https://gna.org/bugs/?group=planner-el ;; Compatibility: Emacs21, Emacs22, Emacs23, XEmacs21 ;; This file is part of Planner. It is not part of GNU Emacs. ;; Planner 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, or (at your option) ;; any later version. ;; Planner 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 Planner; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;;_ + Usage ;; ;; Place planner.el in your load path and add this to your .emacs: ;; ;; (require 'planner) ;; ;; By default and for backward compatibility, the following operations ;; do not have keybindings, and are only accessible from the Planner ;; menu: ;; ;; planner-copy-or-move-region ;; planner-delete-task ;; planner-task-delegated ;; planner-task-pending ;; planner-fix-tasks ;; ;; You may find it easier to install keybindings for those operations by ;; inserting the following in your .emacs file: ;; ;; ;; Note: This changes some of the default key bindings for planner-mode ;; (planner-install-extra-task-keybindings) ;; ;; If you want to change `planner-directory' and some other variables, ;; either use Customize or use `setq'. For example: ;; ;; (setq planner-directory "~/Plans") ;; ;; You can customize Planner. M-x customize-group RET planner RET ;; or see the Options section. ;; ;;; Note: ;; ;; This package extends Emacs Muse to act as a day planner, roughly ;; equivalent to the one used by Franklin-Covey. If they have patents ;; and trademarks and copyrights to prevent me even thinking in terms ;; of their methodology, then I can't believe they care at all about ;; productivity. ;; ;;;_ + Summary ;; ;; * Make a planning file ;; ;; Open a wiki file within your planning directory. By default, ;; planner-directory is set to "~/Plans". You may have to use C-x C-f ;; to open the file. ;; ;; A plan file generally describes a long-term plan. For example, you ;; could make a plan file for your ThesisProject or your ;; ContinuousLearning. Planner.el can help you organize related ideas, ;; tasks and resources into a coherent plan. ;; ;; * Break your plan into stages ;; ;; Start the file with your "vision", or the goal you intend to ;; accomplish. Break this up into parts, and create a Wiki file for ;; each part, with defined milestones which constitute the "goal" for ;; that part. ;; ;; * Write out the tasks for each stage ;; ;; In each sub-plan, list out the tasks necessary to accomplish the ;; milestone. Write them into the file like this: ;; ;; #A _ 1h Call so and so to make a reservation ;; ;; * Decide on a priority for each task ;; ;; The A is the priority of the task. The _ means it isn't done yet, ;; and the 1h is a quick estimate on how long it will task. The time ;; estimates are optional. ;; ;; The priorities break down like this: ;; ;; A: if you don't do it, your plan will be compromised, and you ;; will have to either abort, backtrack, or make profuse apologies ;; to someone ;; ;; B: if you don't do it, your plan will be delayed ;; ;; C: the plan won't be complete until it's done, but there's no ;; pressure to do it now ;; ;; * Schedule the tasks ;; ;; Put your cursor on a line containing a task, and type C-c C-c. ;; This will copy the task to a specific day, which you will be ;; prompted for. The Emacs Calendar pops up, so you can pick a free ;; day (if you use the Emacs diary and appointment system, the ;; Calendar is even more useful). ;; ;; You will now see your new task, with a link back to your planning ;; page. Selecting this link will take you back to that task on the ;; planning page, where you will see that the planning page's task now ;; has a link to the particular day you scheduled the task for. ;; ;; The two tasks (the one on the planning page, and the one on the ;; daily task list) are linked. Changing the status of one (using C-c ;; C-x, or C-c C-s, for example) will change the status of the other. ;; If you forward the task to another day (using C-c C-c on the daily ;; task page), the planning page's link will be updated to refer to ;; the new day. This is so that you can focus on your daily task list ;; during the day, but see an overview of your plan's progress at any ;; time. ;; ;; * Do the work ;; ;; That's it, as far as what planner.el can do. As you complete tasks ;; each day, they will disappear from view. This only happens for ;; today's completed and forwarded tasks. ;; ;; Planning is an art, just as estimating time is an art. It happens ;; with practice, and by thinking about these things. The Commentary ;; below provides a few of my own thoughts on the matter, although I ;; will say that this an art I have yet to truly develop. ;; ;; The `COMMENTARY' file has John Wiegley's original commentary. ;; ;;;_ + And now back to technical matters ;; ;; In order to refresh and renumber all of your tasks according to their ;; actual order in the buffer, simply save the file or call ;; M-x planner-fix-tasks . ;; ;; Here is a summary of the keystrokes available, including a few I ;; did not mention: ;; ;; M-x plan Begin your planning session. This goes to the last ;; day for which there is any planning info (or today if ;; none), allowing you to review, and create/move tasks ;; from that day. ;; ;; C-M-p Raise a task's priority ;; C-M-n Lower a task's priority ;; ;; C-c C-s Mark the task as in progress or delegated ;; C-c C-x Mark the task as finished ;; ;; C-c C-t Create a task associated with the current Wiki page ;; If you are on the opening line of a Note entry, it is ;; assume that the note itself is the origin of the task. ;; C-c C-c Move or copy the current task to another date ;; If the current task is an original (meaning you are in ;; the buffer where's defined, hopefully a planning page) ;; then it will be copied, and the original task will also ;; now point to the copy. If the current task is a copy, ;; it will just be moved to the new day, and the original ;; tasks link will be updated. ;; ;; C-c C-n Jump to today's task page ;; ;; If you call (planner-calendar-insinuate), typing 'n' in the Emacs ;; calendar will jump to today's task page. ;; ;;;_ + Planning and schedules ;; ;; Sometimes you will have appointments during the day to schedule, ;; which "block out" time that might otherwise be spent on tasks. ;; Users are encouraged to use the Emacs Calendar for this, along with ;; Diary Mode (see the Emacs manual) ;;. ;; ;; However, there is a way to do scheduling directly in planner-mode. ;; It requires the external tool "remind" (Debian users type "apt-get ;; install remind". All others go to ;; http://www.roaringpenguin.com/penguin/open_source_remind.php) ;; ;; Once you have remind installed, you will need two scripts in your ;; local bin directory (/usr/local/bin, $HOME/bin, wherever). These ;; scripts can be downloaded from my web site: ;; ;; http://sacha.free.net.ph/notebook/emacs/plan2rem ;; http://sacha.free.net.ph/notebook/emacs/rem2diary ;; ;; Also, download ;; ;; http://sacha.free.net.ph/notebook/emacs/remind.el ;; ;; and put it somewhere in your load path. Take a look at remind.el ;; for more details. You will need to edit a few things to get it ;; to work. ;; Lastly, here is another snippet for your .emacs file. It creates a ;; keybinding in planner-mode, C-c C-w, which jumps you to the ;; Schedule section of that file. ;; (defun planner-goto-schedule () ;; (interactive) ;; (goto-char (point-min)) ;; (unless (re-search-forward "^\\* Schedule\n\n" nil t) ;; (re-search-forward "^\\* Notes") ;; (beginning-of-line) ;; (insert "* Schedule\n\n\n\n") ;; (forward-line -2))) ;; ;; (eval-after-load "planner" ;; '(progn ;; (define-key planner-mode-map [(control ?c) (control ?w)] ;; 'planner-goto-schedule))) ;; The contents of a scheduling section look like this, which is ;; rendered in HTML as a table: ;; ;; * Schedule ;; ;; 8:00 | Wake up ;; 14:00 | Go to the dentist (2:00) ;; 18:00 | Watch TV ;; ;; The start time is given in 24-hour time, with an optional duration ;; occuring in parentheses at the end of the description hs-show(in ;; HOURS:MINUTES). And off you go! ;; ;; You can also organize this as ;; ;; 8:00 | 8:30 | Wake up ;; 14:00 | 16:00 | Go to the dentist ;; 18:00 | 21:00 | Watch TV ;; ;;;_ + Example planning file ;; ;; The format of a planning file is given below. You are responsible ;; for keeping it looking like this. I intentionally did not make ;; planner.el heavy on the UI side of things, too keep it more ;; free-form and open. This lets you adapt it to whatever your ;; particular preferences might be. ;; ;;---------------------------------------------------------------------- ;; * Tasks ;; ;; #A1 _ An open task, very important! ;; #A2 X A closed task (MyPlan) ;; #A3 o A task that's delayed, or delegated (MyPlan) ;; ;; * Notes ;; ;; .#1 This is note number one ;; ;; Notes on note number one! ;; ;; .#2 This weird ".#2" syntax is used because it's what allout.el ;; likes for enumerated lists, and it makes using ;; outline-minor-mode (with allout) very handy. You can omit the ;; leading period if you like, though. It's optional. ;; ;; ---------------------------------------------------------------------- ;; ;;;_ + Other packages that come with the Planner distribution ;; ;; planner-bbdb.el | Link to your contacts ;; planner-diary.el | Thomas Gehrlein's diary integration ;; planner-gnus.el | Link to your mail/news messages ;; planner-id.el | Automatically add unique task IDs ;; planner-notes.el | Create a note index ;; planner-rss.el | Publish your notes as an RSS feed ;; planner-schedule.el | Estimate task completion time ;; planner-timeclock.el | Clock in and clock out ;; planner-w3m.el | Make tasks based on W3M buffers ;; remember.el | Easily remember short notes ;;;_ + Thanks ;; A short, partial list of contributors, those who reported bugs, and ;; those who gave valuable suggestions can be found at ;; http://sacha.free.net.ph/notebook/wiki/PlannerMode.php ;;;_ + Contributors ;; David D. Smith (davidsmith AT acm DOT org) helped links to planner ;; pages be created properly, among other things. ;; Frederik Fouvry fixed a match error by using grouping. ;; Daniel Neri (dne AT mayonnaise DOT net) fixed a couple of typos. ;; Mario Peter (email address unknown) made ;; `planner-in-progress-task-face' use :bold instead of :slant if ;; using XEmacs. ;; Yvonne Thomson (yvonne AT netbrains DOT com DOT au) contributed ;; `planner-annotation-from-info'. ;; Hoan Ton-That (hoan AT ton-that DOT org) had the idea to strip the ;; directory from planner file annotations and contributed the base ;; patch. ;; Michael Olson (mwolson AT gnu DOT org) contributed XHTML 1.1 ;; patches, fixed some bugs that irked him, and did a few other ;; miscellaneous things. ;; Maciej Kalisiak (mac AT cs DOT toronto DOT edu) made a patch that ;; sorts dated tasks before undated ones. Maciej also helped with the ;; separation of the sorting and renumbering processes. ;; Dale P. Smith (dsmich AT adelphia DOT net) contributed a small ;; patch that fixes tasks that are not true wiki names. ;; Stefan Reichör (stefan AT xsteve DOT at) contributed a small patch ;; that saves only modified buffers, and some other patches as well. ;; Chris Parsons made it so that C-u means put note on plan page. ;; Dirk Bernhardt contributed a patch that added the ;; `planner-default-tasks-status' option. ;; Jim Ottaway provided several bugfixes. ;; Dryice Dong Liu made the place to put the annotation in the task ;; description configurable. ;; Angus Lees provided a patch to make planner-sort-tasks stop causing ;; backtraces. ;; Yann Hodique (hodique AT lifl DOT fr) fixed a number of problems ;; with the Muse port of Planner. ;; Peter K. Lee (saint AT corenova DOT com) fixed a few initial errors ;; with missing and malformed functions like `planner-page-exists-p' ;; and `planner-option-customized' ;; Romain Francoise improved match data handling in ;; `planner-browse-position-url'. ;; Win Treese fixed a bug in `planner-save-buffers'. ;; Sven Kloppenburg fixed a regexp. ;; Sergey Vlasov fixed several bugs. ;; Marco Gidde provided a patch that allows Planner to visit a link to ;; a temporary file by visiting its buffer. ;; Trent Buck made things work better when day pages are disabled. ;; Andrew J. Korty made it so that task padding is only used if ;; `planner-use-task-numbers' is non-nil. ;;; Code: ;;;_* Prerequisites (require 'muse-colors) (require 'muse-mode) (require 'muse-project) (require 'muse-html) (require 'sort) (require 'calendar) (require 'font-lock) (require 'info) (require 'easymenu) (condition-case nil (require 'derived) (error nil)) (condition-case nil (require 'overlay) (error nil)) (defvar planner-loaded nil) (defvar planner-version "3.42" "The version of Planner currently loaded.") ;; Compatibility hacks -- these will be removed in the future (defun planner-update-wiki-project () ;; do nothing ) (defvar planner-markup-tags nil) (defun planner-option-customized (sym val) "Set SYM to VAL and update the WikiPlanner project." (set sym val) (when planner-loaded (planner-update-wiki-project))) (defun planner-split-string (string &optional separators omit-nulls) ;; OMIT-NULLS was added in Emacs 22. Remove this when we stop supporting ;; anything before 22, and replace all uses with `split-string'. (let ((res (split-string string separators))) (if omit-nulls (delete "" res) res))) ;;;_* Options (defgroup planner nil "A personal information manager for Emacs." :prefix "planner-" :group 'applications) (defcustom planner-project "WikiPlanner" "The name of this project in `muse-project-alist'." :type 'string :group 'planner) (defcustom planner-initial-page "WelcomePage" "The name of the root plan page that `plan' will find when not using day pages. If you are using day pages (the default), this option is not used." :type 'string :group 'planner) (defcustom planner-publish-dates-first-p nil "Non-nil means put day pages at the top of the index." :type 'boolean :group 'planner) (defcustom planner-use-day-pages t "If non-nil, allow the use of day pages. You can set this to nil if you use plan pages exclusively and don't want to be prompted for dates. If so, then `plan' will bring up the `planner-initial-page' of your planner wiki." :type 'boolean :group 'planner) (defcustom planner-use-plan-pages t "If non-nil, allow the use of plan pages. You can set this to nil if you use day pages exclusively and don't want to be prompted for plans." :type 'boolean :group 'planner) (defcustom planner-mode-hook nil "A hook for Planner mode." :type 'hook :group 'planner) (defcustom planner-annotation-functions '(planner-annotation-from-planner-note planner-annotation-from-planner planner-annotation-from-wiki planner-annotation-from-dired planner-annotation-from-info planner-annotation-from-man planner-annotation-from-woman planner-annotation-from-file-with-position) "Functions tried in order by `planner-create-task-from-buffer'. To change the behavior of `planner-create-task-from-buffer', remove, change the order of, or insert functions in this list." :type 'hook :group 'planner) (defcustom planner-annotation-symbol-string "{}" "The string to be replaced by annotation from `planner-annotation-functions'. If nil or not found in the task title, the annotation will be added to the end." :type 'string :group 'planner) (defcustom planner-use-other-window t "If non-nil, Planner will open planner files in another window." :type 'boolean :group 'planner) (defcustom planner-show-only-existing t "If non-nil, `planner-show' only shows existing files." :type 'boolean :group 'planner) (defcustom planner-reverse-chronological-notes t "*If non-nil, notes are added to the beginning of the section." :type 'boolean :group 'planner) (defcustom planner-create-section-function 'planner-create-at-top "Called when creating a new section. Some functions you can use are `planner-create-at-top' and `planner-create-at-bottom'." :type 'function :group 'planner) (defcustom planner-template-fuzz-factor 5 "Controls the fuzziness of `planner-page-default-p'. Right now, this is the number of additional characters over `planner-day-page-template' allowed in a buffer before `planner-page-default-p' assumes it has been modified." :type 'integer :group 'planner) (defcustom planner-calendar-show-planner-files t "If non-nil, shows a plan file every time a day is selected in Calendar." :type 'boolean :group 'planner) (defcustom planner-day-page-template "* Tasks\n\n\n* Schedule\n\n\n* Notes\n\n\n" "Template to be inserted into blank daily pages. If this is a string, it will be inserted into the blank page. If this is a function, it will be called with no arguments from a blank planner page and should insert the template. If you want to change the name of special sections like Tasks and Notes, update the `planner-sections' option as well." :type '(choice (string :tag "Template") (function :tag "Function")) :group 'planner) (defcustom planner-plan-page-template "* Tasks\n\n\n* Notes\n\n\n" "Template to be inserted into blank plan pages. If this is a string, it will be inserted into the blank page. If this is a function, it will be called with no arguments from a blank planner page and should insert the template. If you want to change the name of special sections like Tasks and Notes, update the `planner-sections' option as well." :type '(choice (string :tag "Template") (function :tag "Function")) :group 'planner) (defcustom planner-default-section 'tasks "Default section when you use `planner-goto' to open a page. If this is a string, it should be a section name. If this is a symbol, the section name is looked up in `planner-sections'." :type '(choice (string :tag "String") (symbol :tag "Symbol")) :group 'planner) (defcustom planner-sections '((tasks . "Tasks") (notes . "Notes")) "Special sections in pages. This option makes it easier to change the names of your sections without modifying a lot of Planner code. If you change this, you may also want to change `planner-day-page-template' and `planner-plan-page-template'. You normally don't need to change these, though." :type '(alist :key symbol :value string) :group 'planner) (defcustom planner-ignored-from-addresses (and user-mail-address (not (string= user-mail-address "")) (regexp-quote user-mail-address)) "Regexp of From headers that may be suppressed in favor of To headers." :group 'planner :type 'regexp) (defcustom planner-dates-relative-to-today-flag nil "Non-nil means relative dates (+1, -1) are always based on today. By default, dates are based on the current page." :group 'planner :type 'boolean) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Task options ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defgroup planner-tasks nil "Planner options related to tasks." :prefix "planner-" :group 'planner) ; Note that if you add another choice other than '.' or '-' here, you'll need ; to grep through the code for [\\.\\-] and replace it with a regex that matches ; all possible date-separators. I thought about making a variable that builds ; all the regexes used elsewhere, but it made the code messy, it seemed, and ; I didn't imagine too many other separators people would want. Myabe '/', but ; that would cause it's own world of hurt. -- bkuhn, 2007-01-09 (defcustom planner-date-separator "." "This character will be used to separate year, month and day numbers when formatting dates" :type '(choice (const :tag "Dates should be in the form YYYY.MM.DD" ".") (const :tag "Dates should be in the form YYYY-MM-DD" "-")) :group 'planner) (defcustom planner-carry-tasks-forward 3 "If non-nil, carry unfinished tasks forward automatically. If a positive integer, scan that number of days in the past. If 0, scan all days for unfinished tasks. If t, scan one day in the past (old behavior). If nil, do not carry unfinished tasks forward." :type '(choice (const :tag "Scan all days" 0) (const :tag "Scan most recent day" t) (const :tag "Do not carry tasks forward" nil) (integer :tag "Number of days to scan")) :group 'planner-tasks) (defcustom planner-marks-regexp "[_oXDCP]" "Regexp that matches status character for a task." :type 'regexp :group 'planner-tasks) (defcustom planner-default-task-priority "B" "Default priority for new tasks created with `planner-create-task'." :type 'string :group 'planner-tasks) (defcustom planner-default-task-status "_" "Default status for new tasks created with `planner-create-task'." :type 'string :group 'planner-tasks) (defcustom planner-add-task-at-end-flag nil "*Non-nil means create tasks at the bottom of the first task block." :group 'planner-tasks :type 'boolean) ;;; Muse ;;;_* Keybindings (defvar planner-mode-map (let ((map (make-sparse-keymap))) (cond ;; XEmacs ((featurep 'xemacs) (set-keymap-parents map muse-mode-map)) ;; Emacs ((fboundp 'set-keymap-parent) (set-keymap-parent map muse-mode-map)) ;; if we can't inherit the keymap, copy it instead (t (setq map (copy-keymap muse-mode-map)))) (define-key map "\C-c\C-n" 'planner-goto-today) ;; moving between daily pages C-c C-j for goto (used to be C-g, ;; but that was confusing) (define-key map "\C-c\C-j\C-d" 'planner-goto) ; goto date (when planner-use-day-pages (define-key map "\C-c\C-j\C-p" 'planner-goto-previous-daily-page) (define-key map "\C-c\C-j\C-n" 'planner-goto-next-daily-page) (define-key map "\C-c\C-j\C-j" 'planner-goto-today) ; for easy typing (define-key map "\C-c\C-j\C-y" 'planner-goto-yesterday) (define-key map "\C-c\C-j\C-t" 'planner-goto-tomorrow) (define-key map "\C-c\C-j\C-r" 'planner-goto-most-recent)) ; recent (define-key map "\C-c\C-t" 'planner-create-task-from-buffer) (define-key map "\C-c\C-c" 'planner-copy-or-move-task) (define-key map "\C-c\C-u" 'planner-raise-task) (define-key map "\C-c\C-d" 'planner-lower-task) (define-key map "\M-p" 'planner-raise-task) (define-key map "\M-n" 'planner-lower-task) (define-key map "\M-\C-p" 'planner-raise-task-priority) (define-key map "\M-\C-n" 'planner-lower-task-priority) (define-key map "\C-c\C-z" 'planner-task-in-progress) (define-key map "\C-c\C-x" 'planner-task-done) (define-key map '[(control ?c) (control ?X)] 'planner-task-cancelled) map) "Keymap used by Planner mode.") (defun planner-install-extra-context-keybindings () "Install extra context-sensitive keybindings. These keybindings conflict with windmove.el, but might be useful. On a task or note, the following keys will move around: Shift-up: `planner-move-up' Shift-down: `planner-move-down' Shift-right: `planner-jump-to-link'" (interactive) (let ((map planner-mode-map)) (define-key map [(shift up)] 'planner-move-up) (define-key map [(shift down)] 'planner-move-down) (define-key map [(shift right)] 'planner-jump-to-link))) ;;; Additional keybindings thanks to Thomas Gehrlein (defun planner-install-extra-task-keybindings () "Install additional task key bindings. Warning! Overwrites some standard key bindings. See function definition for keys added." (let ((map planner-mode-map)) (define-key map "\C-c\C-t" nil) (define-key map "\C-c\C-t\C-t" 'planner-create-task-from-buffer) (define-key map "\C-c\C-t\C-k" 'planner-delete-task) (define-key map "\C-c\C-t\C-u" 'planner-update-task) (define-key map "\C-c\C-t\C-c" 'planner-copy-or-move-task) (define-key map '[(control ?c) (control ?t) (control ?C)] 'planner-copy-or-move-region) (define-key map "\C-c\C-t\C-x" 'planner-task-done) (define-key map '[(control ?c) (control ?t) (control ?X)] 'planner-task-cancelled) (define-key map "\C-c\C-t\C-d" 'planner-task-delegated) (define-key map "\C-c\C-t\C-p" 'planner-task-pending) (define-key map "\C-c\C-t\C-o" 'planner-task-in-progress) (define-key map "\C-c\C-t\C-r" 'planner-raise-task) (define-key map "\C-c\C-t\C-l" 'planner-lower-task) (define-key map "\C-c\C-t\C-n" 'planner-fix-tasks))) ;;; We need some keybindings for note-related functions, too (defun planner-install-extra-note-keybindings () "Install additional note-related key bindings. See function definition for keys added." (let ((map planner-mode-map)) (define-key map "\C-c\C-o" nil) (define-key map "\C-c\C-o\C-o" 'planner-create-note) (define-key map "\C-c\C-o\C-s" 'planner-search-notes) (define-key map "\C-c\C-o\C-b" 'planner-search-notes-with-body) (define-key map "\C-c\C-o\C-n" 'planner-renumber-notes))) ;;;_* Menu ;;; Menu thanks to Thomas Gehrlein (easy-menu-define planner-menu planner-mode-map "Menu of planner mode. See `planner-install-extra-task-keybindings' for additional bindings you can use." (list "Planner" ;; moving between day plan pages (if planner-use-day-pages '("Goto" ["Plan page" planner-goto-plan-page] ["Date" planner-goto] ["Previous page" planner-goto-previous-daily-page] ["Next page" planner-goto-next-daily-page] ["Today" planner-goto-today] ;; do the next two make sense in a menu? ["Yesterday" planner-goto-yesterday] ["Tomorrow" planner-goto-tomorrow] ["Most recent" planner-goto-most-recent]) '["Goto plan page" planner-goto-plan-page]) ;; handling tasks '("Tasks" ["Create" planner-create-task-from-buffer] ["Create from note" planner-create-task-from-note] ["Delete" planner-delete-task] ["Update" planner-update-task] ["Copy or move task" planner-copy-or-move-task] ["Copy or move region" planner-copy-or-move-region] "---" ;; Roughly arranged by frequency, not by chronological sequence ["Mark \"done\"" planner-task-done] ["Mark \"delegated\"" planner-task-delegated] ["Mark \"pending\"" planner-task-pending] ["Mark \"in progress\"" planner-task-in-progress] ["Mark \"cancelled\"" planner-task-cancelled] ["Mark \"open\"" planner-task-open] "---" ["Raise task priority" planner-raise-task-priority] ["Lower task priority" planner-lower-task-priority] ["Format tasks nicely" planner-fix-tasks]) ;; notes '("Notes" ["Create" planner-create-note] ["Create from task" planner-create-note-from-task] "---" ["Search" planner-search-notes] ["Search with body" planner-search-notes-with-body] ["Renumber" planner-renumber-notes]) "---" ;; miscellaneous '["Plan" plan] "---" ;; help/info (now that we have a manual, use it) '["Info manual" (info "planner-el")])) ;;;_* Internal functions ;;;_ + Compatibility ;;;_ + Emacs vs XEmacs (eval-and-compile (defun planner-derived-mode-p (&rest modes) "Non-nil if the current major mode is derived from one of MODES. Uses the `derived-mode-parent' property of the symbol to trace backwards." (if (fboundp 'derived-mode-p) (apply 'derived-mode-p modes) ;; PUBLIC: find if the current mode derives from another. ;; Taken from GNU Emacs 21 subr.el (let ((parent major-mode)) (while (and (not (memq parent modes)) (setq parent (get parent 'derived-mode-parent)))) parent)))) (defalias 'planner-match-string-no-properties 'muse-match-string-no-properties) (defalias 'planner-replace-regexp-in-string 'muse-replace-regexp-in-string) (defalias 'planner-line-beginning-position 'muse-line-beginning-position) (defalias 'planner-line-end-position 'muse-line-end-position) ;;; Handling diary renaming that was official as of 23.1 ;;; Drop this when 23 is the oldest we support. (when (< emacs-major-version 23) (defalias 'diary-list-entries 'list-diary-entries) (defalias 'diary-list-entries-hook 'list-diary-entries-hook) (defalias 'diary-include-other-diary-files 'include-other-diary-files)) ;;; Copied from subr.el (defun planner-copy-overlay (o) "Return a copy of overlay O." (if (fboundp 'copy-overlay) (copy-overlay o) (let ((o1 (make-overlay (overlay-start o) (overlay-end o) ;; FIXME: there's no easy way to find the ;; insertion-type of the two markers. (overlay-buffer o))) (props (overlay-properties o))) (while props (overlay-put o1 (pop props) (pop props))) o1))) ;;; Copied from subr.el (defun planner-remove-overlays (beg end name val) "Clear BEG and END of overlays whose property NAME has value VAL. Overlays might be moved and or split." (if (fboundp 'remove-overlays) (remove-overlays beg end name val) (if (< end beg) (setq beg (prog1 end (setq end beg)))) (save-excursion (dolist (o (overlays-in beg end)) (when (eq (overlay-get o name) val) ;; Either push this overlay outside beg...end ;; or split it to exclude beg...end ;; or delete it entirely (if it is contained in beg...end). (if (< (overlay-start o) beg) (if (> (overlay-end o) end) (progn (move-overlay (planner-copy-overlay o) (overlay-start o) beg) (move-overlay o end (overlay-end o))) (move-overlay o (overlay-start o) beg)) (if (> (overlay-end o) end) (move-overlay o end (overlay-end o)) (delete-overlay o)))))))) ;; Provide a simpler replacement for `remove-if-not' (defun planner-remove-if-not (predicate seq) "Remove all items not satisfying PREDICATE in SEQ. This is a non-destructive function; it makes a copy of SEQ to avoid corrupting the original SEQ." (let (newseq) (dolist (el seq) (when (funcall predicate el) (setq newseq (cons el newseq)))) (nreverse newseq))) ;; Display a warning (defun planner-display-warning (message) "Display the given MESSAGE as a warning." (if (fboundp 'display-warning) (display-warning 'planner message (if (featurep 'xemacs) 'warning :warning)) (let ((buf (get-buffer-create "*Planner warnings*"))) (with-current-buffer buf (goto-char (point-max)) (insert "Warning (planner): " message) (unless (bolp) (newline))) (display-buffer buf) (sit-for 0)))) (defun planner-unhighlight-region (begin end &optional verbose) "Remove all visual highlights in the buffer (except font-lock)." (planner-zap-overlays begin end) (muse-unhighlight-region begin end verbose)) (defun planner-zap-overlays (beg end &optional verbose) "Remove all the planner-related overlays/extents from BEG to END." (if (featurep 'xemacs) (mapcar-extents 'delete-extent nil nil beg end nil 'planner t) (planner-remove-overlays beg end 'planner t))) (defmacro with-planner (&rest body) "Make sure BODY is evaluated in a `planner-mode' buffer." `(if (planner-derived-mode-p 'planner-mode) (progn ,@body) (with-temp-buffer (setq muse-current-project (muse-project planner-project)) (muse-project-set-variables) (planner-mode) ,@body))) (put 'with-planner 'lisp-indent-function 0) (put 'with-planner 'edebug-form-spec '(body)) ;; Use a macro for the setup around planner-update-task so ;; the same setup can be used in planner-multi.el (defmacro with-planner-update-setup (&rest body) "Execute BODY then save buffers according to `planner-tasks-file-behavior'. Also sets some variables to modify font-lock behaviour while updating." (let ((live-buffers (make-symbol "live-buffers"))) `(save-window-excursion (save-excursion (save-restriction (let ((,live-buffers (and (eq planner-tasks-file-behavior 'close) (buffer-list))) (current-buffer (current-buffer))) (prog1 (let ((planner-tasks-file-behavior nil)) ,@body) (when planner-tasks-file-behavior (planner-save-buffers ,live-buffers t current-buffer))))))))) ;; Manually expanded def-edebug-spec so that we don't have to pull ;; edebug in (put 'with-planner-update-setup 'edebug-form-spec '(body)) (defalias 'planner-current-file 'muse-current-file) (defun planner-file-alist (&optional no-check-p pages) "Return possible Wiki filenames in `planner-project'. On UNIX, this list is only updated if one of the directories' contents have changed or NO-CHECK-P is non-nil. On Windows, it is always reread from disk. PAGES is ignored." (muse-project-file-alist planner-project no-check-p)) (defun planner-find-file (wiki &optional command directory) "Open the Planner page WIKI by name. If COMMAND is non-nil, it is the function used to visit the file. If DIRECTORY is non-nil, it is the directory in which the Wiki page will be created if it does not already exist." (muse-project-find-file (planner-link-base wiki) planner-project command directory)) (defalias 'planner-page-name 'muse-page-name) (defun planner-link-base (link) "Return the page or URL named by LINK." (when (string-match muse-explicit-link-regexp link) (setq link (planner-match-string-no-properties 1 link))) (when (string-match "#" link) (setq link (substring link 0 (match-beginning 0)))) link) (defalias 'planner-time-less-p 'muse-time-less-p) (defalias 'planner-private-p 'muse-project-private-p) (defalias 'planner-follow-name-at-point 'muse-follow-name-at-point) (defalias 'planner-next-reference 'muse-next-reference) (defalias 'planner-previous-reference 'muse-previous-reference) ;; FIXME: Code that uses `planner-directory' should be changed to deal ;; with multiple directories. (defun planner-directory () (car (cadr (muse-project planner-project)))) (defun planner-published-file (file &optional output-dir style) (unless output-dir (setq output-dir (and muse-publishing-current-output-path (file-name-directory muse-publishing-current-output-path)))) (when output-dir (muse-publish-output-file file output-dir style))) (defun planner-remove-links (description) "Remove explicit links from DESCRIPTION." (let (start) (while (setq start (string-match muse-explicit-link-regexp description start)) (setq description (replace-match (or (match-string 2 description) (match-string 1 description)) t t description))) description)) (defun planner-make-link (link &optional name single) "Return a Wiki link to LINK with NAME as the text. If SINGLE is non-nil, treat it as a single link. If LINK is already a valid link, replace it's description by NAME" (cond ((or (null link) (string= link "")) "") ((string-match muse-explicit-link-regexp link) (muse-make-link (match-string 1 link) name)) (t (muse-make-link link name)))) ;;;_ + Diary ;; In here instead of planner-diary because planner-appt and ;; planner-cyclic use it as well. Contributions from Sergey Vlasov. (defun planner-list-diary-entries (file date &optional number) "Get list of diary entries in FILE for NUMBER days starting with DATE. The list has the same form as returned by `list-diary-entries', but this function tries to undo the changes which `list-diary-entries' does to the diary buffer." (require 'diary-lib) ;; The code to restore the buffer was copied from `include-other-diary-files' (save-window-excursion (save-excursion (let* ((diary-file file) (diary-list-entries-hook '(diary-include-other-diary-files)) (diary-display-hook 'ignore) (diary-hook nil) (d-buffer (find-buffer-visiting diary-file)) (diary-modified (when d-buffer (set-buffer d-buffer) (buffer-modified-p)))) (unwind-protect (diary-list-entries date (or number 1)) (let ((d-buffer (find-buffer-visiting diary-file))) (when d-buffer (set-buffer d-buffer) (subst-char-in-region (point-min) (point-max) ?\^M ?\n t) (setq selective-display nil) (set-buffer-modified-p diary-modified)))))))) ;;;_ + Mode (defcustom planner-align-tasks-automatically t "Non-nil means align tasks whenever a planner file is saved." :type 'boolean :group 'planner) (defcustom planner-sort-tasks-automatically t "Non-nil means sort tasks whenever a planner file is saved." :type 'boolean :group 'planner) (defcustom planner-renumber-tasks-automatically nil "Non-nil means renumber tasks whenever a planner file is saved." :type 'boolean :group 'planner) (defcustom planner-renumber-notes-automatically nil "Non-nil means renumber notes whenever a planner file is saved." :type 'boolean :group 'planner) ;;;###autoload (define-derived-mode planner-mode muse-mode "Planner" "A personal information manager for Emacs. \\{planner-mode-map}" ;; because we're not inheriting from normal-mode, we need to ;; explicitly run file variables if the user wants to (condition-case err (hack-local-variables) (error (message "File local-variables error: %s" (prin1-to-string err)))) ;; check to see if the mode changed (when (eq major-mode 'planner-mode) (let ((hook (if (boundp 'write-file-functions) 'write-file-functions 'write-file-hooks))) (add-hook hook 'planner-renumber-notes-maybe t t) (add-hook hook 'planner-sort-tasks-maybe t t) (add-hook hook 'planner-renumber-tasks-maybe t t) (add-hook hook 'planner-align-tasks-maybe t t)) (planner-setup-highlighting) (when (fboundp 'easy-menu-add) (easy-menu-add planner-menu planner-mode-map)) (planner-prepare-file))) ;; (when (and font-lock-mode muse-mode-highlight-p) ;; (muse-colors-buffer)))) (defvar planner-date-regexp "\\<\\([1-9][0-9][0-9][0-9]\\)[\\.\\-]\\([0-9]+\\)[\\.\\-]\\([0-9]+\\)\\>") (defun planner-setup-highlighting () "Set up fontification for planner." (add-hook 'muse-colors-buffer-hook 'planner-zap-overlays t t) (add-hook 'muse-colors-buffer-hook 'planner-highlight-tasks t t) (add-hook 'muse-colors-buffer-hook 'planner-highlight-notes t t) (add-to-list 'muse-colors-markup (list planner-date-regexp t 'muse-colors-implicit-link) t) (muse-configure-highlighting 'muse-colors-markup muse-colors-markup) (set (make-local-variable 'font-lock-unfontify-region-function) 'planner-unhighlight-region) (set (make-local-variable 'font-lock-defaults) '(nil t nil nil beginning-of-line (font-lock-fontify-region-function . muse-colors-region) (font-lock-unfontify-region-function . planner-unhighlight-region)))) (defun planner-muse-handle-date-link (&optional string) "If STRING or point has a date, match and return it." (when (if string (string-match planner-date-regexp string) (looking-at planner-date-regexp)) (match-string 0 string))) (custom-add-option 'muse-implicit-link-functions 'planner-muse-handle-date-link) (add-hook 'muse-implicit-link-functions 'planner-muse-handle-date-link t) ;;;_ + Wiki pages (defun planner-strip-whitespace (string) "Remove all whitespace from STRING. Return the modified string." (with-temp-buffer (insert string) (goto-char (point-min)) (while (re-search-forward "[\r\n\t ]+" nil t) (replace-match "")) (buffer-string))) (defun planner-page-default-p (&optional buffer) "Return t if this plan page can be safely deleted. If the contents of this plan page are the same as the value of `planner-day-page-template' or the plan page is empty, then no information has been added and the page can safely be removed. If BUFFER is given, considers the planner page in BUFFER instead. Override this if `planner-day-page-template' is a function instead of a string." (with-current-buffer (or buffer (current-buffer)) (when (and (stringp planner-day-page-template) (not (> (buffer-size) (+ (length planner-day-page-template) planner-template-fuzz-factor)))) (let ((body (planner-strip-whitespace (buffer-string)))) (or (= (length body) 0) (string= body (planner-strip-whitespace planner-day-page-template))))))) (defvar planner-delete-file-function 'delete-file "Function called to remove a planner file from the current wiki.") (defun planner-maybe-remove-file () "Delete the planner file if it does not contain new information." (if (planner-page-default-p (current-buffer)) (let ((filename buffer-file-name)) (set-buffer-modified-p nil) (kill-buffer (current-buffer)) (when (file-exists-p filename) (funcall planner-delete-file-function filename))) (kill-buffer (current-buffer)))) (defun planner-prepare-file () "Insert some standard sections into an empty planner file." (when (= (buffer-size) 0) (let ((template (if (and (planner-page-name) (string-match planner-date-regexp (planner-page-name))) planner-day-page-template planner-plan-page-template))) (if (functionp template) (funcall template) (insert template)) (set-buffer-modified-p nil)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Compatibility (defun planner-link-href (url name) "Return an href string for URL and NAME." (muse-publish-url url name)) (defun planner-link-target (link) "Return the URL or page in LINK." (if (string-match muse-explicit-link-regexp link) (planner-match-string-no-properties 1 link) link)) (defun planner-link-name (link) "Return the name for LINK." (if (string-match muse-explicit-link-regexp link) (planner-match-string-no-properties 2 link) link)) (defun planner-link-anchor (link) "Return the anchor part of LINK." (setq link (planner-link-target link)) (if (string-match "#" link) (substring link (1+ (match-beginning 0))))) (defun planner-visit-link (link &optional other-window) "Visit the URL or link named by LINK. REFRESH-BUFFER is an optional buffer to refresh on saving the visited page. This makes the bad link face in the linking buffer go away." (if (string-match muse-url-regexp link) (muse-browse-url link other-window) (setq link (planner-link-target link)) (let ((tag (planner-link-anchor link)) base-buffer) ;; use match data from planner-link-anchor (when tag (setq link (if (= (match-beginning 0) 0) ;; If there is an anchor but no link, default ;; to the current page. nil (substring link 0 (match-beginning 0))))) (when link (setq base-buffer (get-buffer link)) (if (and base-buffer (not (buffer-file-name base-buffer))) ;; If file is temporary (no associated file), just switch to ;; the buffer (if other-window (switch-to-buffer-other-window base-buffer) (switch-to-buffer base-buffer)) (let ((project (muse-project-of-file))) (if project (muse-project-find-file link project (and other-window 'find-file-other-window)) (if other-window (find-file-other-window link) (find-file link)))))) (when tag (goto-char (point-min)) (or (re-search-forward (concat "^\\.?#" (regexp-quote tag) "\\>") nil t) (when (string-match "^anchor-\\(.*\\)" tag) (re-search-forward (concat "^\\.?#" (regexp-quote (match-string 1 tag)) "\\>") nil t))))))) (defalias 'planner-add-protocol 'muse-protocol-add) (defalias 'planner-page-exists-p 'planner-page-file) (defun planner-local-page-p (link) "Return non-nil if LINK seems to belong to the current wiki." (and link (not (or (string-match ":\\|/" (planner-link-base link)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun planner-list-daily-files (&optional exclude-temp) "Return an unsorted, unique list of daily files. If EXCLUDE-TEMP is non-nil, ignore unsaved buffers." ;; get a list of all files ;; (save-some-buffers t (lambda () (equal 'planner-mode major-mode))) (let ((buffers (buffer-list)) files) (mapcar (lambda (item) (when (string-match planner-date-regexp (car item)) (unless (rassoc (cdr item) files) (setq files (cons item files))))) (planner-file-alist)) (unless exclude-temp (while buffers (with-current-buffer (car buffers) (when (and (equal 'planner-mode major-mode) (planner-page-name) (string-match planner-date-regexp (planner-page-name))) (unless (assoc (planner-page-name) files) (add-to-list 'files (cons (planner-page-name) (buffer-file-name)))))) (setq buffers (cdr buffers)))) files)) (defun planner-get-day-pages (&optional from to exclude-temp) "Return a descending list of day pages from FROM to TO (inclusive). If EXCLUDE-TEMP is non-nil, ignore unsaved pages." (sort (delq nil (mapcar (lambda (item) (and (car item) (or (not from) (string-lessp from (car item)) (equal from (car item))) (or (not to) (string-lessp (car item) to) (equal (car item) to)) item)) (planner-list-daily-files exclude-temp))) (lambda (l r) (string-lessp (car r) (car l))))) ;;;_ + Date (defvar planner-calendar-selected-date nil "Temporary storage for date selected from calendar.") (defvar planner-use-calendar-flag t "*If non-nil, show calendar popup when reading a date.") (defun planner-read-date (&optional prompt force-read) "Prompt for a date string in the minibuffer. If PROMPT is non-nil, display it as the prompt string. If FORCE-READ is non-nil, prompt for a date even when we are not using day pages." (save-window-excursion (when (or planner-use-day-pages force-read) (let ((old-buffer (current-buffer))) (when planner-use-calendar-flag (calendar)) (let ((old-map (copy-keymap calendar-mode-map))) (unwind-protect (progn (define-key calendar-mode-map [return] 'planner-calendar-select) (define-key calendar-mode-map [mouse-1] 'planner-calendar-select) (setq planner-calendar-selected-date nil) (let ((text (read-string (format "%s %s" (or prompt "When") (format-time-string (concat "(%Y" planner-date-separator "%m" planner-date-separator "%d, %m" planner-date-separator "%d, %d): ")))))) (or planner-calendar-selected-date (with-current-buffer old-buffer (planner-expand-name text))))) (setq calendar-mode-map old-map))))))) (defvar planner-timewarp-date nil "*Date to timewarp to for planner. Should be a string of the form YYYY.MM.DD. If nil, do not timewarp.") ;; This should be handy for remembering lots of notes onto particular days. (defun planner-timewarp (date) "Timewarp to DATE." (interactive (list (let ((planner-timewarp-date nil)) (planner-read-date)))) (setq planner-timewarp-date date) (if date (message "Timewarped to %s" date) (message "Timewarped back to the present"))) (defun planner-today () "Return the filename of the current date." (if planner-use-day-pages (or planner-timewarp-date (planner-date-to-filename (decode-time (current-time)))) planner-initial-page)) (defun planner-date-to-filename (date) "Return the planner filename corresponding to DATE. DATE is a list (month day year) or an internal date representation." (let ( (date-form-string (concat "%04d" planner-date-separator "%02d" planner-date-separator "%02d") ) ) (progn (if (= (length date) 3) (format date-form-string (elt date 2) (elt date 0) (elt date 1)) (if (= (length date) 2) (setq date (decode-time date))) (format date-form-string (elt date 5) ; year (elt date 4) ; month (elt date 3)))))) ; day (defun planner-calculate-date-from-day-offset (origin offset) "From ORIGIN, calculate the date OFFSET days into the past or future. ORIGIN can be a buffer name, a list of the form (MONTH DAY YEAR), or an internal date representation. If OFFSET is positive, returns a date in the future. If OFFSET is negative, returns the date -OFFSET days in the past. Return an object that is the same type as ORIGIN." (cond ((stringp origin) (let ((date (planner-filename-to-calendar-date origin))) (planner-date-to-filename (encode-time 0 0 0 (+ (elt date 1) offset) (elt date 0) (elt date 2))))) ((= (length origin) 2) (encode-time 0 0 0 (+ (elt origin 1) offset) (elt origin 0) (elt origin 2))) ((= (length origin) 3) (let ((result (decode-time (encode-time 0 0 0 (+ (elt origin 1) offset) (elt origin 0) (elt origin 2))))) (list (elt result 4) (elt result 3) (elt result 5)))))) (defun planner-get-previous-existing-day (date) "Return the planner file immediately before DATE. DATE is a filename or a list (month day year). When called from a planner file, DATE defaults to the date of this file, otherwise it defaults to today. Returns an object of the same type as DATE." (let ((newdate (if (listp date) (planner-date-to-filename date) date)) (result nil)) ;; beginning of hackish part (mapcar (lambda (elt) (when (and (or (not result) (not (or (string= elt result) (string< elt result)))) (string< elt newdate)) (setq result elt))) (mapcar 'car (planner-list-daily-files))) (if result (if (listp date) (planner-filename-to-calendar-date result) result) (error "No previous planner file")))) (defun planner-get-next-existing-day (date) "Return the existing planner file immediately after DATE. DATE is a filename or a list (month day year). When called from a planner file, DATE defaults to the date of this file, otherwise it defaults to today. Returns an object of the same type as DATE." (let ((newdate (if (listp date) (planner-date-to-filename date) date)) (result nil)) ;; beginning of hackish part (mapcar (lambda (elt) (when (and (or (not result) (string< elt result)) (not (or (string= elt newdate) (string< elt newdate)))) (setq result elt))) (mapcar 'car (planner-list-daily-files))) (if result (if (listp date) (planner-filename-to-calendar-date result) result) (error "No next planner file")))) (defun planner-yesterday () "Return the date of yesterday." (planner-calculate-date-from-day-offset (planner-today) -1)) (defun planner-tomorrow () "Return the date of tomorrow." (planner-calculate-date-from-day-offset (planner-today) 1)) (defcustom planner-expand-name-favor-future-p nil "If non-nil, `planner-expand-name' defaults to future dates." :type 'boolean :group 'planner) (defcustom planner-expand-name-default "." "What an empty string means in `planner-expand-name'. \".\" means today." :type '(choice (const :tag "Today" ".") (const :tag "None" nil) string) :group 'planner) (defvar planner-expand-name-days-alist '(("sun" . 0) ("mon" . 1) ("tue" . 2) ("wed" . 3) ("thu" . 4) ("fri" . 5) ("sat" . 6)) "Abbreviations for `planner-expand-name'.") (defun planner-expand-name (name) "Expand the given NAME to its fullest form. This typically means that dates like 3.31 will become 2001.03.31. NOTE: This function no longer uses the current buffer filename for defaults." (let ((now (if planner-use-day-pages (planner-filename-to-calendar-date (planner-today)) (planner-filename-to-calendar-date (planner-date-to-filename (decode-time (current-time)))))) name-year name-month name-day) (when (string-match "^\\s-*$" name) (setq name (or planner-expand-name-default "nil"))) (cond ((string= "nil" name) nil) ((string= "." name) (if (not planner-use-day-pages) (planner-date-to-filename now) (planner-today))) ((string-match (concat "^\\([1-9][0-9][0-9][0-9][\\.\\-]\\)?" "\\(\\([0-9]+\\)[\\.\\-]\\)?" "\\([0-9]+\\)\\(#.*\\)?$") name) (setq name-year (if (match-string 1 name) (string-to-number (match-string 1 name)) (nth 2 now))) (setq name-month (if (match-string 3 name) (string-to-number (match-string 3 name)) (nth 0 now))) (setq name-day (if (match-string 4 name) (string-to-number (match-string 4 name)) (nth 1 now))) (when (and planner-expand-name-favor-future-p (planner-time-less-p (encode-time 59 59 23 name-day name-month name-year) (current-time))) (cond ((match-string 1 name)) ; Do nothing if the year is specified ((match-string 2 name) (setq name-year (1+ name-year))) ((match-string 4 name) (setq name-month (1+ name-month))))) (planner-date-to-filename (encode-time 59 59 23 name-day name-month name-year))) ((string-match "^\\([-+]\\)\\s-*\\([0-9]+\\)$" name) ;; Today + or - that number of days (planner-calculate-date-from-day-offset (if (not planner-use-day-pages) (planner-date-to-filename now) (if (or planner-dates-relative-to-today-flag (not (planner-page-name)) (not (save-match-data (string-match planner-date-regexp (planner-page-name))))) (planner-today) (planner-page-name))) (string-to-number (concat (match-string 1 name) (match-string 2 name))))) ((let ((case-fold-search nil)) (string-match (concat "^\\([-+]\\)\\s-*\\([0-9]*\\)\\s-*\\(" (mapconcat 'car planner-expand-name-days-alist "\\|") "\\)\\s-*\\([\\.\\-]\\|\\(\\(\\([0-9]+[\\.\\-]\\)?[0-9]+[\\-\\.]\\)?[0-9]+\\)\\)?$") name)) (let* ((day (cdr (assoc (match-string 3 name) planner-expand-name-days-alist))) (offset (string-to-number (concat (match-string 1 name) (if (and (match-string 2 name) (not (string= (match-string 2 name) ""))) (match-string 2 name) "1")))) (base-date (planner-filename-to-calendar-date (if (and (match-string 4 name) (not (string= (match-string 4 name) ""))) (planner-expand-name (match-string 4 name)) (if (not planner-use-day-pages) (planner-date-to-filename now) (if (or planner-dates-relative-to-today-flag (not (planner-page-name)) (not (save-match-data (string-match planner-date-regexp (planner-page-name))))) (planner-today) (planner-page-name))))))) (planner-date-to-filename (calendar-gregorian-from-absolute (calendar-dayname-on-or-before day (+ (calendar-absolute-from-gregorian base-date) (* offset 7) (if (< offset 0) 6 0))))))) (t name)))) (defun planner-get-current-date-filename () "Return the date of the daily page currently being viewed. If no daily page is being viewed, return today's date." (if (string-match planner-date-regexp (planner-page-name)) (planner-page-name) (planner-today))) (defun planner-filename-to-calendar-date (filename) "Return the date of the planning file FILENAME. Date is a list (month day year)." (unless (string-match planner-date-regexp filename) (error "Not convertible to a date %s" filename)) (list (string-to-number (match-string 2 filename)) ; month (string-to-number (match-string 3 filename)) ; day (string-to-number (match-string 1 filename)))) ; year ;;;_ + Sections (defun planner-narrow-to-section (section &optional create) "Widen to the whole page and narrow to the section labelled SECTION. If CREATE is non-nil, create the section if it is not found. Return non-nil if SECTION was found." (interactive "MSection: ") (widen) (unless (stringp section) (setq section (cdr (assoc section planner-sections)))) (goto-char (point-min)) (when (or (re-search-forward (concat "^*\\s-+" (regexp-quote section) "\\s-*$") nil t) (and create (funcall planner-create-section-function section) (goto-char (point-min)) (re-search-forward (concat "^*\\s-+" (regexp-quote section) "\\s-*$") nil t))) (let ((beg (match-beginning 0)) (end (if (re-search-forward "^*\\s-+" nil t) (match-beginning 0) (point-max)))) (narrow-to-region beg end) t))) (defun planner-delete-section (section) "Delete the named SECTION." (unless (planner-derived-mode-p 'planner-mode) (error "This is not a planner buffer")) (unless (stringp section) (setq section (cdr (assoc section planner-sections)))) (widen) (goto-char (point-min)) (when (re-search-forward (concat "^\\*\\s-+" section "\\(\\s-*\\)$") nil t) (let ((beg (planner-line-beginning-position)) (end (if (re-search-forward "^* " nil t) (planner-line-beginning-position) (point-max)))) (delete-region beg end)))) (defun planner-delete-section-text (section) "Delete the text of the named SECTION." (unless (planner-derived-mode-p 'planner-mode) (error "This is not a planner buffer")) (unless (stringp section) (setq section (cdr (assoc section planner-sections)))) (widen) (goto-char (point-min)) (when (re-search-forward (concat "^\\*\\s-+" section "\\(\\s-*\\)$") nil t) (let ((beg (point)) (end (if (re-search-forward "^* " nil t) (planner-line-beginning-position) (point-max)))) (delete-region beg end) (goto-char (planner-line-beginning-position))))) (defun planner-seek-to-first (&optional section) "Positions the point at the specified SECTION, or Tasks if not specified." (interactive) (unless section (setq section planner-default-section)) (unless (stringp section) (setq section (cdr (assoc section planner-sections)))) (widen) (goto-char (point-min)) (if (re-search-forward (concat "^\\*\\s-+" section "\\(\\s-*?\\)$") nil t) (let ((old (point)) new) (forward-line 1) (if (re-search-forward "[^\\s-]" nil t) (progn (goto-char (planner-line-beginning-position)) (unless (looking-at "^\\*\\s-") (setq new (point))))) (goto-char (or new old)) (unless new (forward-line 1) (when (or (looking-at "^\\*\\s-+") (> (forward-line 1) 0)) (insert "\n")) (when (or (looking-at "^\\*\\s-+") (> (forward-line 1) 0)) (insert "\n")) (when (looking-at "^\\*\\s-+") (forward-line -1)))) ;; Section not found, so create it. (funcall planner-create-section-function section))) (defun planner-create-at-top (section) "Create SECTION at top of file." (goto-char (point-min)) (let ((buffer-status (buffer-modified-p))) (insert "* " section "\n\n") (set-buffer-modified-p buffer-status))) (defun planner-create-at-bottom (section) "Create SECTION at bottom of file." (goto-char (point-max)) (let ((buffer-status (buffer-modified-p))) (insert "\n* " section "\n\n") (set-buffer-modified-p buffer-status))) ;;;_ + Basic annotation ;;;###autoload (defun planner-annotation-as-kill (arg) "Copy the current annotation into the kill ring. When called with a prefix argument, prompt for the link display name." (interactive "P") (let* ((link (run-hook-with-args-until-success 'planner-annotation-functions)) (link-name (if arg (read-string (format "Link name for %s: " link))))) (unless (or (not (stringp link-name)) (string= link-name "")) (setq link (planner-make-link link link-name t))) (if (not (stringp link)) (message "No annotation can be made") (message "Copied '%s' to the kill-ring" link) (kill-new link)))) (custom-add-option 'planner-annotation-functions 'planner-annotation-as-kill) (defun planner-annotation-from-planner-note () "Return a link to the current page. Call when the point is on the first line of the note." (when (and (planner-derived-mode-p 'planner-mode) (planner-page-name)) (save-excursion (goto-char (planner-line-beginning-position)) (when (looking-at ".\\(#[0-9]+\\)") (planner-make-link (concat (planner-page-name) (planner-match-string-no-properties 1)) (concat (planner-page-name) (planner-match-string-no-properties 1)) t))))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-planner-note) (defun planner-annotation-from-planner () "Return a wiki link to the current wiki page. Date pages are not linked." (when (and (planner-derived-mode-p 'planner-mode) (planner-page-name)) (cond ((string-match planner-date-regexp (planner-page-name)) "") ; None for date pages (t (planner-make-link (planner-page-name) nil t))))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-planner) (defun planner-annotation-from-wiki () "Return the interwiki link to the current wiki page." (when (and (planner-derived-mode-p 'muse-mode) muse-current-project (muse-page-name)) (concat "[[" (car muse-current-project) "::" (muse-page-name) "]]"))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-wiki) (defun planner-annotation-from-dired () "Return the `default-directory' of the current Dired buffer." (when (eq major-mode 'dired-mode) (planner-make-link default-directory))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-dired) (defcustom planner-annotation-use-relative-file nil "If t, use relative file links always. If a function, it is called with the file name. Return value of t means use relative file links." :group 'planner :type '(choice (const :tag "Always use relative file links" t) (const :tag "Never use relative file links" nil) function)) (defcustom planner-annotation-strip-directory nil "If non-nil, strip the directory part of the filename from link text." :group 'planner :type 'boolean) (defcustom planner-annotation-format-local-file-name nil "If non-nil, use the result of `planner-annotation-format-local-file-name'." :group 'planner :type '(choice (const :tag "Use filename as is" nil) function)) (defun planner-annotation-from-file () "Return the filename of the current buffer. If `planner-annotation-use-relative-file' is t or a function that returns non-nil, a relative link is used instead. If `planner-annotation-strip-directory' is non-nil, the directory is stripped from the link description." (when buffer-file-name (planner-make-link (if (or (and (functionp planner-annotation-use-relative-file) (funcall planner-annotation-use-relative-file (buffer-file-name))) (equal planner-annotation-use-relative-file t)) (file-relative-name (buffer-file-name) (planner-directory)) (if (functionp planner-annotation-format-local-file-name) (funcall planner-annotation-format-local-file-name buffer-file-name) buffer-file-name)) (when planner-annotation-strip-directory (file-name-nondirectory buffer-file-name)) t))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-file) ;;;###autoload (defun planner-annotation-from-file-with-position () "Return the filename and cursor position of the current buffer. If `planner-annotation-use-relative-file' is t or a function that returns non-nil, a relative link is used instead. If `planner-annotation-strip-directory' is non-nil, the directory is stripped from the link description." (when buffer-file-name (planner-make-link (concat "pos://" (if (or (and (functionp planner-annotation-use-relative-file) (funcall planner-annotation-use-relative-file (buffer-file-name))) (equal planner-annotation-use-relative-file t)) (file-relative-name (buffer-file-name) (planner-directory)) buffer-file-name) "#" (number-to-string (point))) (if planner-annotation-strip-directory (file-name-nondirectory buffer-file-name) buffer-file-name) t))) ;;;###autoload (defun planner-browse-position-url (url) "If this is a position URL, jump to it." (when (string-match "^pos://\\(.+\\)#\\([0-9]+\\)$" url) (let ((file (match-string 1 url)) (pos (string-to-number (match-string 2 url)))) (find-file file) (goto-char pos) t))) ;;;###autoload (defun planner-resolve-position-url (id) "Replace ID with the blog, web or e-mail address of the BBDB record." (save-match-data (when (string-match "\\`pos://\\(.+\\)#\\([0-9]+\\)" id) (match-string 1 id)))) (planner-add-protocol "pos://" 'planner-browse-position-url 'planner-resolve-position-url) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-file-with-position) ;;;_ + Tasks (defcustom planner-create-task-hook nil "Functions to run after a task has been created. Point will be on the same line as the task." :type 'hook :group 'planner-tasks) (defcustom planner-create-task-from-buffer-hook nil "Functions to run after a task has been created from a buffer. This will be run before `planner-create-task-hook'. Point will be on the same line as the task." :type 'hook :group 'planner-tasks) (defcustom planner-task-dates-favor-future-p nil "*If this is non-nil, favor future dates for task creation or movement." :type 'boolean :group 'planner-tasks) (defcustom planner-default-page "TaskPool" "Default page for tasks. This is set to the current planner page, or the last page used if not on a plan page." :type 'string :group 'planner-tasks) (defcustom planner-tasks-file-behavior 'close "Controls behavior of task creation and updates. If 'close, newly-opened files are saved and closed. If 'save, newly-opened files are saved and left open. If nil, no actions will be taken." :group 'planner-tasks :type '(choice (const :tag "Save and close opened files" 'close) (const :tag "Save opened files" 'save) (const :tag "Do nothing" nil))) (defcustom planner-tasks-never-suppress-fixing-flag t "Non-nil means always sort, renumber and align tasks whenever files are saved." :group 'planner-tasks :type 'boolean) (defcustom planner-sort-undated-tasks-equivalent "9999.99.99" "Date considered for undated tasks. This option controls task sorting on plan pages. By default, undated tasks are sorted after dated tasks." :group 'planner-tasks :type '(choice (const :tag "Sort undated tasks after dated tasks" "9999.99.99") (const :tag "Sort undated tasks before dated tasks" "") string)) (defcustom planner-sort-tasks-key-function 'planner-sort-tasks-default-key "Function called to determine the sorting key for the current line." :group 'planner-tasks :type 'function) (defcustom planner-use-task-numbers nil "Non-nil means number tasks. This allows you to refer to past tasks if your tasks are numbered appropriately. If you set this to nil, you can save space in your plan files." :type 'boolean :group 'planner-tasks) ;;;_ + Information (defun planner-task-info-from-string (page-name string) "On the planner page PAGE-NAME, parse STRING and return the task as a list. Argument PAGE-NAME is used to determine whether this is a link from a plan page or a date page." (with-planner (when (string-match "#\\([A-C]\\)\\([0-9]*\\)\\s-+\\(.\\)\\s-+\\(.+\\)" string) (let ((priority (planner-match-string-no-properties 1 string)) (number (planner-match-string-no-properties 2 string)) (status (planner-match-string-no-properties 3 string)) (description (planner-match-string-no-properties 4 string)) (case-fold-search nil) link-text link plan date) (when (= (length number) 0) (setq number nil)) (cond ((string-match "\\s-+(\\(\\[\\[\\([^])]+\\)\\]\\[\\([^])]+\\)\\]\\]\\))\\s-*$" description) (setq link-text (match-string 1 description)) (setq link (match-string 2 description)) (setq description (replace-match "" t t description))) ((string-match "\\s-+(\\(\\[\\[\\([^])]+\\)\\]\\]\\))\\s-*$" description) (setq link-text (match-string 1 description)) (setq link (match-string 2 description)) (setq description (replace-match "" t t description))) ((string-match "\\s-+(\\([^)]+\\))\\s-*$" description) (setq link-text (match-string 1 description)) (setq link (match-string 1 description)) (setq description (replace-match "" t t description))) ((string-match "\\s-+$" description) (setq description (replace-match "" t t description)))) (when link (setq link (planner-link-base link-text))) (unless (planner-local-page-p link) (setq link nil)) (if (string-match planner-date-regexp page-name) ;; We're on a date page, so the link page (if any) should be the ;; planner page. (progn (setq date page-name) (setq plan (and link (unless (string-match planner-date-regexp link) link)))) ;; We're on a planner page, so the link page (if any) will be the plan (setq plan (and page-name (unless (string-match planner-date-regexp page-name) page-name))) (when (and link (string-match planner-date-regexp link)) (setq date (match-string 0 link)))) (list page-name priority number status description link link-text plan date))))) (defun planner-task-info-override (task-info properties) "Replace fields in TASK-INFO with PROPERTIES. Acceptable properties are: page-name priority number status description link link-text plan date." (let ((fields '(page-name priority number status description link link-text plan date)) result) (while task-info (setq result (cons (car (let ((search (memq (car fields) properties))) (if search (cdr search) task-info))) result)) (setq fields (cdr fields)) (setq task-info (cdr task-info))) (nreverse result))) (defun planner-current-task-info () "Parse the current line and return the task information as a list." (planner-task-info-from-string (planner-page-name) (buffer-substring (planner-line-beginning-position) (planner-line-end-position)))) (defun planner-task-page (info) "Return the page of a task given INFO." (nth 0 info)) (defun planner-task-priority (info) "Return the priority of a task given INFO." (nth 1 info)) (defun planner-task-number (info) "Return the number of a task given INFO." (nth 2 info)) (defun planner-task-status (info) "Return the status of a task given INFO." (nth 3 info)) (defun planner-task-description (info) "Return the description of a task given INFO." (nth 4 info)) (defun planner-task-link (info) "Return the page linked to by a task given INFO." (nth 5 info)) (defun planner-task-link-text (info) "Return the link text of a task given INFO." (nth 6 info)) (defun planner-task-plan (info) "Return the planner page of a task given INFO." (nth 7 info)) (defun planner-task-date (info) "Return the planner date of a task given INFO." (nth 8 info)) (defun planner-task-link-as-list (info) "Return a list of all the pages this task is on." (delq nil (list (nth 7 info) (nth 8 info)))) ;;;_ + Creation (defvar planner-create-task-from-info-function 'planner-create-task-from-info-basic "Function for creating tasks. Should accept the same arguments as `planner-create-task-from-info-basic'.") (defun planner-create-task-from-info (info &optional priority number status description link-text date plan) "Create a task in the date and plan pages based on INFO. Optional arguments PRIORITY, NUMBER, STATUS, DESCRIPTION, LINK-TEXT, DATE, and PLAN override those in INFO." (funcall planner-create-task-from-info-function info priority number status description link-text date plan)) (defun planner-create-task-from-info-basic (info &optional priority number status description link-text date plan) "Create a task in the date and plan pages based on INFO. Optional arguments PRIORITY, NUMBER, STATUS, DESCRIPTION, LINK-TEXT, DATE, and PLAN override those in INFO." (save-window-excursion (save-excursion ;; page-name priority number status description ;; link link-text plan date ;; Create the task in the plan page (let ((plan-page (or plan (planner-task-plan info))) (date-page (or date (planner-task-date info))) (live-buffers (and (equal planner-tasks-file-behavior 'close) (buffer-list)))) (when plan-page (if (string-match planner-date-regexp plan-page) (setq plan-page nil))) (when (and plan-page (not (string= plan-page ""))) (planner-find-file plan-page) (planner-seek-task-creation-point) (insert (planner-format-task info priority number status description (planner-make-link date-page) (planner-make-link date-page)) "\n")) ;; Create the task in the date page (when (and date-page (not (string= date-page ""))) (planner-goto date-page) (planner-seek-task-creation-point) (insert (planner-format-task info priority number status description (or link-text (planner-task-link-text info)) plan-page) "\n")) (forward-line -1) (run-hooks 'planner-create-task-hook) (when planner-tasks-file-behavior (planner-save-buffers live-buffers t)))))) (defvar planner-task-format "#%s%s %s %s%s" "Format used by `planner-format-task' when inserting new tasks.") (defun planner-format-task (task-info &optional priority number status description link-text link) "Return a string containing TASK-INFO ready to be inserted into a page. Non-nil values of PRIORITY, NUMBER, STATUS, DESCRIPTION, LINK-TEXT, and LINK override TASK-INFO." (format planner-task-format (or priority (planner-task-priority task-info)) (if planner-use-task-numbers (format "%-2s" (or number (planner-task-number task-info) "")) "") (or status (planner-task-status task-info)) (or description (planner-task-description task-info)) (let ((text (or link-text (and link (planner-make-link link)) (planner-task-link-text task-info)))) (if (and text (not (equal text ""))) (concat " (" text ")") "")))) ;;;_ + Scheduling (defun planner-copy-or-move-region (beg end &optional date muffle-errors) "Move all tasks from BEG to END to DATE. If this is the original task, it copies it instead of moving. Most of the time, the original should be kept in a planning file, but this is not required. If BEG is at the end of a line, the first task moved will be the one on the following line. If END is at the beginning of a line, the last task moved will be the one on the previous line. If MUFFLE-ERRORS is non-nil, no errors will be reported." (interactive "r") (unless date (setq date (let ((planner-expand-name-favor-future-p (or planner-expand-name-favor-future-p planner-task-dates-favor-future-p))) (planner-read-date)))) (let ((start (if (< beg end) beg end)) (finish (if (< beg end) end beg)) (buffer (current-buffer)) (error-count 0) (count 0) (live-buffers (when (equal planner-tasks-file-behavior 'close) (buffer-list)))) ;; Invoke planner-copy-or-move-task on each line in reverse (let ((planner-tasks-file-behavior nil) (task-info) prev-point) (save-excursion (save-restriction (narrow-to-region (and (goto-char (1+ start)) (planner-line-beginning-position)) (and (goto-char (1- finish)) (min (point-max) (1+ (planner-line-end-position))))) (when planner-add-task-at-end-flag (reverse-region (point-min) (point-max))) (goto-char (point-max)) (setq prev-point (point)) (while (not (and (bobp) (= (point) prev-point))) (forward-line 0) (setq prev-point (point)) (setq task-info (planner-current-task-info)) ;; Don't move completed or cancelled tasks (if (and task-info (not (member (planner-task-status task-info) '("C" "X")))) (condition-case err (when (planner-copy-or-move-task date) (setq count (1+ count))) (error (unless (or muffle-errors (not (interactive-p))) (message "Error with %s: %s" (planner-task-description (planner-current-task-info)) err) (setq error-count (1+ error-count))) (forward-line -1) nil)) (forward-line -1))) (when planner-add-task-at-end-flag (reverse-region (point-min) (point-max))) (when (and (not muffle-errors) (not error-count) (> error-count 0) (interactive-p)) (message (if (> error-count 1) "%d errors." "%d error.") error-count))))) (when planner-tasks-file-behavior (planner-save-buffers live-buffers)) (set-buffer buffer) count)) ; Return the number of tasks moved. ;;;_ + Navigation (defvar planner-jump-to-linked-task-function 'planner-jump-to-linked-task-basic "Function to jump to a linked task. Function should have one optional parameter: TASK-INFO.") (defun planner-jump-to-linked-task (&optional task-info) "Display the task page linked to by the current task or TASK-INFO." (funcall planner-jump-to-linked-task-function task-info)) (defun planner-jump-to-linked-task-basic (&optional task-info) "Display the task page linked to by the current task or TASK-INFO." (interactive) (let* ((task-info (or task-info (planner-current-task-info))) (link (and task-info (planner-task-link task-info)))) (when (planner-local-page-p link) (planner-find-file (planner-task-link task-info)) (widen) (goto-char (point-min)) (when (search-forward (planner-task-description task-info) nil t) (beginning-of-line) t)))) ;;;_ + Convenience (defvar planner-history-list nil "History list for pages.") (defvar planner-read-name-function 'planner-read-name-single "Function to call in order to read the names of pages.") (defun planner-read-name (file-alist &optional prompt initial) "Read the name of a valid Wiki page from minibuffer. FILE-ALIST is a list of (page-name . filename) entries. If PROMPT is non-nil, it is used as the prompt string. If INITIAL is specified, it is used as a reasonable default." (funcall planner-read-name-function file-alist prompt initial)) (defun planner-read-name-single (file-alist &optional prompt initial) "Read the name of a valid Wiki page from minibuffer with completion. FILE-ALIST is a list of (page-name . filename) entries. If PROMPT is non-nil, it is used as the prompt string. If INITIAL is specified, it is used as a reasonable default." (let* ((default planner-default-page) (str (completing-read (format "%s(default: %s) " (or prompt "Page: ") default) file-alist nil nil initial 'planner-history-list))) (cond ((or (null str) (= (length str) 0)) default) ((string= str "nil") nil) (t str)))) (defun planner-read-name-no-completion (names &optional prompt initial) "Read the name of a valid Wiki page from minibuffer without completion. FILE-ALIST is a list of (page-name . filename) entries. If PROMPT is non-nil, it is used as the prompt string. If INITIAL is specified, it is used as a reasonable default." (let* ((default planner-default-page) (str (read-string (format "%s(default: %s) " (or prompt "Page: ") default) initial 'planner-history-list default))) (cond ((or (null str) (= (length str) 0)) default) ((string= str "nil") nil) (t str)))) (defun planner-read-non-date-page (file-alist &optional prompt initial) "Prompt for a page name that does not match `planner-date-regexp'. Base completion on FILE-ALIST. If PROMPT is non-nil, use that as the prompt. If INITIAL is non-nil, use that as the initial contents of the minibuffer." (planner-read-name (delq nil (mapcar (lambda (item) (unless (string-match (concat "^\\(?:" planner-date-regexp "\\)$") (car item)) item)) (copy-alist file-alist))) prompt initial)) (defvar planner-find-task-function 'planner-find-task-basic "Function to find a task based on INFO and POINT.") (defun planner-find-task (info &optional point) "Move point to the character before the task described by INFO. If POINT is specified, start search from that point." (funcall planner-find-task-function info point)) (defun planner-find-task-basic (info &optional point) "Move point to the character before the task described by INFO. If POINT is specified, start search from that point." (goto-char (or point (point-min))) (when (re-search-forward (concat "^#[A-C][0-9]*\\s-+.\\s-+" (regexp-quote (planner-task-description info))) nil t) (goto-char (planner-line-beginning-position)))) (defun planner-tasks-equal-p (task-a task-b) "Return t if TASK-A and TASK-B are equivalent. This is true if they have the same value for priority, status, description, plan and date." (and (string= (or (planner-task-priority task-a) "") (or (planner-task-priority task-b) "")) (string= (or (planner-task-status task-a) "") (or (planner-task-status task-b) "")) (string= (or (planner-task-description task-a) "") (or (planner-task-description task-b) "")) (string= (or (planner-task-plan task-a) "") (or (planner-task-plan task-b) "")) (string= (or (planner-task-date task-a) "") (or (planner-task-date task-b) "")))) (defun planner-save-buffers (&optional buffer-list suppress-fixing skip-buffer) "Save all planner buffers. If BUFFER-LIST is a list of buffers, close all buffers not found in that list. If SUPPRESS-FIXING is non-nil, do not perform any planner-related modifications such as task sorting. If SKIP-BUFFER is non-nil, do not save that buffer." (interactive) (setq suppress-fixing (and (not planner-tasks-never-suppress-fixing-flag) suppress-fixing)) (mapcar (lambda (buffer) (unless (eq buffer skip-buffer) (with-current-buffer buffer ;; Save all planner buffers (when (and (planner-derived-mode-p 'planner-mode) buffer-file-name (planner-page-name) (not (string= "" (planner-page-name)))) ;; SUPPRESS-FIXING is negated in the following forms because ;; it makes more sense to let planner-save-buffers do the ;; usual actions when the parameter is omitted. (let ((planner-sort-tasks-automatically (and planner-sort-tasks-automatically (not suppress-fixing))) (planner-renumber-tasks-automatically (and planner-renumber-tasks-automatically (not suppress-fixing))) (planner-align-tasks-automatically (and planner-align-tasks-automatically (not suppress-fixing))) (planner-renumber-notes-automatically (and planner-renumber-notes-automatically (not suppress-fixing))) (planner-tasks-save-behavior nil) (planner-id-update-automatically nil)) (when (buffer-modified-p) (save-buffer))) (when (and buffer-list (not (memq buffer buffer-list))) (kill-buffer nil)))))) (buffer-list))) ;;;_ + Extraction (defvar planner-task-regexp (concat "^#[A-C][0-9]*\\s-+.\\s-+") "Regexp used to match tasks.") (defvar planner-live-task-regexp "^#[ABC][0-9]*\\s-+[_oDP]\\s-+" "Regular expression matching \"live\" tasks. A task is live if it is not finished and it is not cancelled.") (defun planner-extract-tasks (pages &optional condition) "Parse PAGES and extract all tasks. If CONDITION is non-nil, it should be a function that accepts the task info as an argument and returns t if the task should be added to the list." (with-temp-buffer (unless (consp (car pages)) (let ((list (planner-file-alist))) (setq pages (mapcar '(lambda (page) (cons page (cdr (assoc page list)))) pages)))) (let (result) (while pages (erase-buffer) (insert-file-contents (cdar pages)) (goto-char (point-max)) (while (re-search-backward "^#[A-C]" nil t) (let ((info (planner-task-info-from-string (caar pages) (buffer-substring (planner-line-beginning-position) (planner-line-end-position))))) (when (and info (if condition (funcall condition info) t)) (setq result (append (list info) result))))) (setq pages (cdr pages))) result))) (defun planner-extract-tasks-with-status (pages status) "Return all tasks on PAGES with the specified STATUS." (planner-extract-tasks pages (lambda (item) (equal (planner-task-status item) status)))) (defun planner-tasks-tag (beg end attrs) "Replace the region BEG to END with a report of tasks. If status is specified in ATTRS, list tasks matching that status only. To negate the sense of a match, use a regexp." (delete-region beg end) (let* ((status (cdr (assoc "status" attrs))) (tasks (planner-extract-tasks (planner-get-day-pages nil nil t) (if status (lambda (item) (string-match status (planner-task-status item))) nil)))) (while tasks (insert (planner-make-link (planner-task-page (car tasks)) nil t) " | " (planner-task-priority (car tasks)) " | " (planner-task-status (car tasks)) " | " (planner-task-description (car tasks)) "\n") (setq tasks (cdr tasks))))) (defvar planner-on-date-page nil "Internal variable used in `planner-sort-tasks-default-key'.") (defun planner-sort-tasks-default-key () "Provide old sorting behavior. Day pages sort by status and priority. Plan pages sort by date, status and priority." (if planner-on-date-page (planner-sort-tasks-basic) (planner-sort-tasks-by-date))) (defun planner-sort-tasks-basic () "Sort tasks by status (_PDXC) and priority (ABC)." (skip-chars-forward "#ABC") (let ((case-fold-search t) (ch (char-before)) status) (skip-chars-forward "0123456789 ") (setq status (char-after)) (+ ;(read (current-buffer)) (cond ((eq status ?P) 1000) ((eq status ?D) 2000) ((eq status ?X) 3000) ((eq status ?C) 4000) (t 0)) (cond ((eq ch ?A) 100) ((eq ch ?B) 200) ((eq ch ?C) 300) (t 0))))) (defun planner-sort-tasks-by-date () "Sort tasks by date, status and priority." (skip-chars-forward "#ABC") (let ((ch (char-before)) status) (skip-chars-forward "0123456789 ") (setq status (char-after)) (goto-char (planner-line-end-position)) (skip-chars-backward "]) ") (format "%1c%1c%10s" (if (or (= status ?X) (= status ?C)) status ?\ ) ch (if (= (skip-chars-backward "0123456789.") -10) (buffer-substring (point) (+ 10 (point))) planner-sort-undated-tasks-equivalent)))) (defun planner-sort-tasks-by-link () "Sort tasks by status, priority and link." (let ((info (planner-current-task-info))) (concat ;(read (current-buffer)) (cond ((string= (planner-task-status info) "P") "1") ((string= (planner-task-status info) "D") "2") ((string= (planner-task-status info) "X") "3") ((string= (planner-task-status info) "C") "4") (t "0")) (planner-task-priority info) (or (planner-task-link info) "")))) (defun planner-sort-tasks () "Sort the tasks. On day pages, sort according to priority and position. On plan pages, sort according to status, priority, date, and position." (interactive) (let ((case-fold-search nil) (planner-on-date-page (string-match planner-date-regexp (planner-page-name))) (old-task (planner-current-task-info)) (line-offset (- (point) (planner-line-beginning-position))) (old-point (point))) (goto-char (point-min)) (while (re-search-forward "^#[A-C][0-9]*" nil t) (goto-char (match-beginning 0)) (let ((here (point))) (while (and (char-after) (= (char-after) ?#)) (forward-line 1)) (save-restriction (narrow-to-region here (point)) (goto-char here) (condition-case err (sort-subr nil 'forward-line 'end-of-line planner-sort-tasks-key-function nil nil) (wrong-number-of-arguments ; OLD EMACS, 5 args (sort-subr nil 'forward-line 'end-of-line planner-sort-tasks-key-function nil))) (goto-char (point-max))))) (if old-task (progn (planner-find-task old-task) (forward-char line-offset)) (goto-char old-point)) nil)) ; Must return nil because of write-file-functions (defun planner-sort-tasks-maybe () "Sort tasks depending on `planner-sort-tasks-automatically'." (when planner-sort-tasks-automatically (planner-sort-tasks))) (defun planner-renumber-tasks () "Update task numbering to be in sequence once again." (interactive) (let ((old-point (point))) (goto-char (point-min)) (let ((counters (list (cons "A" 1) (cons "B" 1) (cons "C" 1)))) (while (re-search-forward "^#\\([A-C]\\)\\([0-9]+\\)" nil t) (let ((counter (assoc (match-string 1) counters))) (replace-match (number-to-string (cdr counter)) t t nil 2) (setcdr counter (1+ (cdr counter)))))) (goto-char old-point)) nil) ; Must return nil because of write-file-functions (defun planner-renumber-tasks-maybe () "Renumber tasks depending on `planner-renumber-tasks-automatically'." (when planner-renumber-tasks-automatically (planner-renumber-tasks))) (defun planner-fix-tasks () "Sort, renumber and align tasks." (interactive) (planner-sort-tasks) (planner-renumber-tasks) (planner-align-tasks)) ;;;_ + Notes ;;;###autoload (defun planner-create-note (&optional page) "Create a note to be remembered in PAGE (today if PAGE is nil). If `planner-reverse-chronological-notes' is non-nil, create the note at the beginning of the notes section; otherwise, add it to the end. Position point after the anchor." (interactive (list (and (planner-derived-mode-p 'planner-mode) (planner-page-name)))) (planner-goto (or page (and (planner-derived-mode-p 'planner-mode) (planner-page-name)) (planner-today))) (planner-seek-to-first 'notes) (save-restriction (when (planner-narrow-to-section 'notes) (let ((total 0)) (goto-char (point-min)) (while (re-search-forward "^\.#\\([0-9]+\\)\\s-+" nil t) (setq total (max total (string-to-number (match-string 1))))) (if planner-reverse-chronological-notes (progn (goto-char (point-min)) (forward-line 1) (skip-chars-forward "\n")) (goto-char (point-max)) (skip-chars-backward "\n") (when (= (forward-line 1) 1) (insert "\n")) (when (= (forward-line 1) 1) (insert "\n"))) (insert ".#" (number-to-string (1+ total)) " ") (unless (eobp) (save-excursion (insert "\n\n"))) (1+ total))))) (defun planner-delete-note () "Delete the current note." (interactive) (save-window-excursion (let ((info (planner-current-note-info))) (when info (save-window-excursion (when (planner-jump-to-linked-note info) (save-restriction (planner-narrow-to-note) (delete-region (point-min) (point-max))))) (save-restriction (planner-narrow-to-note) (delete-region (point-min) (point-max))))))) (defun planner-format-note (info &optional anchor title timestamp link body) "Return the string representation of INFO. ANCHOR, TITLE, TIMESTAMP, LINK and BODY override INFO if present." (unless anchor (setq anchor (planner-note-anchor info))) (unless title (setq title (planner-note-title info))) (unless timestamp (setq timestamp (planner-note-timestamp info))) (unless link (setq link (planner-note-link info))) (unless body (setq body (planner-note-body info))) (concat (if (and anchor (not (string= "" anchor))) (concat ".#" anchor " ") "") title (if (and timestamp (not (string= "" timestamp))) (concat " " timestamp) "") (if (and link (not (string= "" link))) (concat " (" link ")") "") (if (and body (not (string= "" body))) body ""))) (defun planner-update-note () "Copy the text from this note to the linked note, if any." (interactive) (save-window-excursion (let ((info (planner-current-note-info)) text) (save-restriction (when (planner-narrow-to-note) (setq text (buffer-substring-no-properties (point-min) (point-max))) ;; Get rid of the anchor. (when (string-match "^\\.#[0-9]+\\s-+" text) (setq text (replace-match "" nil t text))) ;; Get rid of the link (when (string-match "\\s-+(\\[\\[.+?\\]\\])" text) (setq text (replace-match "" nil t text))))) ;; Insert the new body (when (planner-jump-to-linked-note) (save-restriction (when (planner-narrow-to-note) (goto-char (point-min)) (skip-chars-forward ".#0-9") (delete-region (point) (point-max)) (insert " " text) (goto-char (point-min)) (goto-char (planner-line-end-position)) (insert " (" (planner-make-link (concat (planner-note-page info) "#" (planner-note-anchor info))) ")"))))))) ;; Case 1a: Date and plan page exist, new plan page wanted ;; Case 1b: Date page exists, no plan yet, plan page wanted ;; Case 2: Date and plan page exist, no plan page wanted ;; Case 3: No date, just plan page (defun planner-replan-note (page) "Change or assign the plan page for the current note. PAGE-NAME is the new plan page for the note." (interactive (list (planner-read-non-date-page (planner-file-alist) nil (planner-note-link-text (planner-current-note-info))))) (let ((info (planner-current-note-info t))) (when (and page (or (string= page (planner-note-plan info)) (string= page (planner-note-date info)))) (error "Same plan page")) (when (null (or page (planner-note-date info))) (error "Cannot unplan note without day page")) (save-window-excursion ;; Delete the old plan note (when (planner-note-plan info) (when (string-match planner-date-regexp (planner-note-page info)) (planner-jump-to-linked-note info)) (save-restriction (planner-narrow-to-note) (delete-region (point-min) (point-max)))) (let (new) (when page ;; Create note on plan page (setq new (planner-create-note page)) (insert (planner-format-note info "" nil nil (if (planner-note-date info) (planner-make-link (concat (planner-note-date info) "#" (planner-note-anchor info))) "")))) ;; Update note on date page, if any (forward-line -1) (when (planner-note-date info) (if (string-match planner-date-regexp (planner-note-page info)) (progn (planner-find-file (planner-note-date info)) (goto-char (point-min)) (re-search-forward (concat "^\\.#" (planner-note-anchor info) "\\s-") nil t)) (planner-jump-to-linked-note info)) (save-restriction (planner-narrow-to-note) (delete-region (point-min) (point-max)) (insert (planner-format-note info nil nil nil (if new (planner-make-link (concat (planner-link-base page) "#" (number-to-string new))) ""))))))))) ;; Improvements: ;; ;; - Link back to the task? If we can figure out how to stably link to ;; a task in the first place... ;; ;; - Should plan-page-p default to t? be a customizable variable? What ;; should it be called? I have the urge to write ;; planner-create-note-from-task-behavior which can have the ;; following values: 'day, 'plan, 'copy, 'xref ... (defun planner-create-note-from-task (&optional plan-page-p) "Create a note based on the current task. Argument PLAN-PAGE-P is used to determine whether we put the new note on the task's plan page or on the current page." (interactive "P") (let ((task-info (planner-current-task-info)) note-num) (when task-info ;; If PLAN-PAGE-P and the task has a plan page, create a note on ;; the plan page. If not, create it on the current page. (when (and plan-page-p (string= (planner-task-date task-info) (planner-task-page task-info))) (planner-jump-to-linked-task task-info)) (setq note-num (planner-create-note (planner-page-name))) (save-excursion (save-window-excursion (when (planner-find-task task-info) (planner-edit-task-description (concat (planner-task-description task-info) " " (planner-make-link (concat (planner-page-name) "#" (number-to-string note-num)) (format "(%d)" note-num))))))) (insert " " (planner-task-description task-info) "\n\n")))) (defun planner-create-note-from-context (&optional plan-page-p) "Create a note based on the current context. If on a task item, call `planner-create-note-from-task'. Anywhere else, call `Footnote-add-footnote' if footnote has been loaded, else, call `planner-create-note'." ) (defun planner-narrow-to-note (&optional page note-number) "Narrow to the specified note. Widen and return nil if note is not found. If PAGE is nil, use current page. If NOTE-NUMBER is nil, use current note. Undefined behavior if PAGE is (non-nil and not today) and NOTE-NUMBER is nil." (when page (planner-goto page)) (save-excursion (let (beginning) (if note-number (progn (goto-char (point-min)) (when (re-search-forward (concat "^\\.#" note-number) nil t) (setq beginning (match-beginning 0)))) (goto-char (planner-line-end-position)) (when (re-search-backward "^\\.#[0-9]+" nil t) (setq beginning (planner-line-beginning-position)))) (when beginning ;; Search for the end (forward-line 1) (narrow-to-region beginning (or (save-excursion (and (re-search-forward "^\\(\\.#\\|* \\)" nil t) (match-beginning 0))) (point-max))) t)))) (defun planner-note-page (note-info) "Return the page specified by NOTE-INFO." (elt note-info 0)) (defun planner-note-anchor (note-info) "Return the anchor specified by NOTE-INFO." (elt note-info 1)) (defun planner-note-title (note-info) "Return the title specified by NOTE-INFO." (elt note-info 2)) (defun planner-note-timestamp (note-info) "Return the timestamp specified by NOTE-INFO." (elt note-info 3)) (defun planner-note-link (note-info) "Return the link specified by NOTE-INFO." (elt note-info 4)) (defun planner-note-link-text (note-info) "Return the link text specified by NOTE-INFO." (elt note-info 4)) (defun planner-note-body (note-info) "Return the timestamp specified by NOTE-INFO." (elt note-info 5)) (defun planner-note-date (note-info) "Return the date for NOTE-INFO." (cond ((string-match planner-date-regexp (planner-note-page note-info)) (planner-note-page note-info)) ((and (planner-note-link note-info) (string-match planner-date-regexp (planner-note-link note-info))) (planner-link-base (planner-note-link note-info))))) (defun planner-note-plan (note-info) "Return the date for NOTE-INFO." (cond ((null (string-match planner-date-regexp (planner-note-page note-info))) (planner-note-page note-info)) ((and (planner-note-link note-info) (null (string-match planner-date-regexp (planner-note-link note-info)))) (planner-link-base (planner-note-link note-info))))) (defun planner-current-note-info (&optional include-body) "Parse the current note and return the note information as a list. The list is of the form (PAGE ANCHOR TITLE TIMESTAMP LINK BODY). If INCLUDE-BODY is non-nil, the list will include the body of the note." (save-excursion (save-restriction (when (planner-narrow-to-note) (goto-char (point-min)) (when (looking-at "^\\.#\\([0-9]+\\)\\s-+\\(.+\\)") (let ((anchor (planner-match-string-no-properties 1)) (title (planner-match-string-no-properties 2)) timestamp link) (when (string-match (concat "\\s-+(\\(" (if (featurep 'planner-multi) (concat "\\(" muse-explicit-link-regexp "\\)" "\\(" (regexp-quote planner-multi-separator) muse-explicit-link-regexp "\\)*") muse-explicit-link-regexp) "\\))\\s-*$") title) (setq link (planner-match-string-no-properties 1 title)) (setq title (replace-match "" nil t title))) (when (string-match "\\s-*\\([0-9]+:[0-9][0-9]\\)" title) (setq timestamp (planner-match-string-no-properties 1 title)) (setq title (replace-match "" nil t title))) (list (planner-page-name) anchor title timestamp link (and include-body (buffer-substring-no-properties (planner-line-end-position) (point-max)))))))))) (defun planner-search-notes-internal (regexp &optional limit include-body) "Return an alist of all notes in daily plan pages containing REGEXP. The alist is of the form ((REFERENCE TITLE BODY) (REFERENCE TITLE BODY) ...). If LIMIT is non-nil, do not search days before LIMIT. If INCLUDE-BODY is non-nil, return the body text, else return nil." (let ((pages (planner-get-day-pages limit t)) filename page start anchor text results title page-results) (while pages (setq page (caar pages) filename (cdar pages)) (with-temp-buffer (when (file-readable-p filename) (insert-file-contents filename) (setq start nil) (setq page-results nil) ;; Find the first note (when (re-search-forward "\\.\\(#[0-9]+\\)\\s-+\\(.*\\)" nil t) (setq start (match-beginning 2)) (setq anchor (match-string 1)) (setq title (match-string 2))) (while (re-search-forward "\\.\\(#[0-9]+\\)\\s-+\\(.*\\)" nil t) ;; The text between start and (1- (match-beginning 0)) ;; is the note body. (when (save-excursion (goto-char (planner-line-beginning-position)) (save-match-data (re-search-backward regexp start t))) (add-to-list 'page-results (list (concat filename anchor) (concat page anchor) title (if include-body (buffer-substring-no-properties start (planner-line-beginning-position)))))) (setq start (match-beginning 2)) (setq anchor (match-string 1)) (setq title (match-string 2))) (when start (goto-char (point-max)) (when (save-excursion (re-search-backward regexp start t)) (add-to-list 'page-results (list (concat filename anchor) (concat page anchor) title (if include-body (buffer-substring-no-properties start (point))))))) (when planner-reverse-chronological-notes (setq page-results (nreverse page-results)))) (setq results (append page-results results))) (setq pages (cdr pages))) results)) (defun planner-jump-to-linked-note (&optional note-info) "Display the note linked to by the current note or NOTE-INFO if non-nil." (interactive) (setq note-info (or note-info (planner-current-note-info))) (when (and (planner-note-link note-info) (save-window-excursion (planner-visit-link (planner-note-link note-info)))) (planner-visit-link (planner-note-link note-info)) (widen) t)) (defun planner-renumber-notes () "Update note numbering." (interactive) (let ((old-point (point)) (counter 1)) (goto-char (if planner-reverse-chronological-notes (point-max) (point-min))) (while (if planner-reverse-chronological-notes (re-search-backward "^\\.#\\([0-9]+\\)" nil t) (re-search-forward "^\\.#\\([0-9]+\\)" nil t)) (replace-match (number-to-string counter) t t nil 1) (when planner-reverse-chronological-notes (goto-char (planner-line-beginning-position))) (setq counter (1+ counter))) (goto-char old-point)) nil) ; Must return nil because of write-file-functions (defun planner-renumber-notes-maybe () "Renumber notes depending on `planner-renumber-notes-automatically'." (when planner-renumber-notes-automatically (planner-renumber-notes))) ;;;_ + Highlighting (defgroup planner-fontlock nil "Font-locking for planner.el pages." :prefix "planner-" :group 'planner) (defface planner-completed-task-face (if (featurep 'xemacs) '((t (:strikethru t :foreground "gray"))) '((t (:strike-through t :foreground "gray")))) "Face for completed tasks." :group 'planner-fontlock) (defface planner-cancelled-task-face (if (featurep 'xemacs) '((t (:strikethru t :foreground "gray"))) '((t (:strike-through t :foreground "gray")))) "Face for cancelled tasks." :group 'planner-fontlock) (defface planner-delegated-task-face '((t (:underline t))) "Face for delegated tasks." :group 'planner-fontlock) (defface planner-in-progress-task-face (if (featurep 'xemacs) '((t (:bold t))) '((t (:slant oblique)))) "Face for tasks in progress." :group 'planner-fontlock) (defface planner-high-priority-task-face '((t (:foreground "red"))) "Face for high-priority tasks." :group 'planner-fontlock) (defface planner-medium-priority-task-face '((t (:foreground "green"))) "Face for medium-priority tasks." :group 'planner-fontlock) (defface planner-low-priority-task-face '((t (:foreground "blue"))) "Face for low-priority tasks." :group 'planner-fontlock) (defface planner-note-headline-face '((((class color) (background light)) (:foreground "dark slate blue" :bold t)) (((class color) (background dark)) (:foreground "pale turquoise" :bold t)) (t (:bold t))) "Face for note headlines." :group 'planner-fontlock) ;; Thanks to Oliver (oik AT gmx DOT net) (defun planner-align-tasks () "Align tasks neatly. You can add this to `write-file-functions'to have the tasks automatically lined up whenever you save. For best results, ensure `planner-align-tasks' is run after `planner-renumber-tasks'." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "^#\\([A-C]\\)\\([0-9]*\\)\\(\\s-+\\)" nil t) (replace-match ;; Ugly hack! ;; (make-string (max (- (length (match-string 2))) 0) ?\s) ;; is better, but relies on a CVSism. (let ((length (length (match-string 2)))) (cond ((and (= length 0) planner-use-task-numbers) " ") ((= length 1) " ") (t " "))) t t nil 3))) nil) ; Return nil so that we can add this to write-file-functions (defun planner-align-tasks-maybe () "Align tasks depending on `planner-align-tasks-automatically'." (when planner-align-tasks-automatically (planner-align-tasks))) (defun planner-align-table () "Align table neatly. Take account of links which hides characters when displayed. Perhaps, guts of this should really be inside muse..." (interactive) (save-excursion (when (fboundp 'align-regexp) (align-regexp (point-min) (point-max) "\\(\\s-*\\)|" 1 1 t)) (goto-char (point-min)) (while (re-search-forward (concat "^" muse-explicit-link-regexp) nil t) (let ((link (match-string 1)) (desc (match-string 2))) (insert " " (make-string (if desc (+ 2 (length link)) 0) (aref " " 0))))))) ;; FIXME: Is there a better way to do this? (defun planner-highlight-region (beg end identifier priority properties) "Add the specified text properties to the overlay or region. BEG and END are the start and end of the region. IDENTIFIER is a symbol that identifies this particular overlay. PRIORITY controls how important this overlay is. PROPERTIES is a list of properties or attributes to apply." (if (featurep 'xemacs) (let ((extent (make-extent beg end))) (set-extent-properties extent properties) (set-extent-property extent 'priority priority)) (if (functionp 'overlay-put) (progn (let ((overlay (make-overlay beg end))) (overlay-put overlay identifier t) (overlay-put overlay 'planner t) (overlay-put overlay 'priority priority) (while properties (overlay-put overlay (car properties) (cadr properties)) (setq properties (cddr properties))))) (add-text-properties beg end properties)))) (defcustom planner-hide-task-status-when-highlighting nil "*If non-nil, hide task status when font-locking." :type 'boolean :group 'planner-fontlock) (defun planner-highlight-tasks (beg end &optional verbose) "Highlight tasks from BEG to END. VERBOSE is ignored." (goto-char beg) (while (re-search-forward (concat "^#\\([A-C]\\)\\([0-9]*\\)\\s-+\\(" planner-marks-regexp "\\)\\s-") end t) (let ((mark (match-string 3)) (priority (match-string 1)) faces) (setq faces (append (cond ((string= priority "A") '(planner-high-priority-task-face)) ((string= priority "B") '(planner-medium-priority-task-face)) ((string= priority "C") '(planner-low-priority-task-face))) (cond ((string= mark "X") '(planner-completed-task-face)) ((string= mark "D") '(planner-delegated-task-face)) ((string= mark "C") '(planner-cancelled-task-face)) ((string= mark "o") '(planner-in-progress-task-face))))) (if (featurep 'xemacs) (mapcar (lambda (face) (when face (planner-highlight-region (match-beginning 0) (match-end 3) 'planner-task 50 (list 'face face)))) faces) (planner-highlight-region (match-beginning 0) (match-end 3) 'planner-task 50 (list 'face (mapcar 'face-attr-construct faces)))) (planner-highlight-region (match-end 3) (planner-line-end-position) 'planner-task 51 (list 'face (cond ((string= mark "X") 'planner-completed-task-face) ((string= mark "D") 'planner-delegated-task-face) ((string= mark "C") 'planner-cancelled-task-face) ((string= mark "o") 'planner-in-progress-task-face)))) (when planner-hide-task-status-when-highlighting (planner-highlight-region (match-beginning 3) (1+ (match-end 3)) 'planner-task 50 (list 'invisible t)))))) (defun planner-highlight-notes (beg end &optional verbose) "Highlight notes as second-level headers from BEG to END. VERBOSE is ignored." (goto-char beg) (while (re-search-forward "^\\.#\\([0-9]+\\) [^(\n]+" end t) (add-text-properties (match-beginning 0) (match-end 0) '(face planner-note-headline-face)))) (defun planner-notes-get-headlines (&optional limit) "Return note headlines on the current page. If LIMIT is non-nil, return only that many from the top." (when (stringp limit) (setq limit (string-to-number limit))) (let (headlines) (save-excursion (save-restriction (widen) (goto-char (point-min)) (while (and (re-search-forward "^.\\(#[0-9]+\\)\\s-+\\(.+\\)" nil t) (if limit (> limit 0) t)) (add-to-list 'headlines (cons (planner-match-string-no-properties 1) (planner-match-string-no-properties 2)) t) (if limit (setq limit (1- limit)))))) headlines)) ;;;_* Indexing ;; I want to compress the list of day pages. Arranging them by month ;; may be a good strategy, although a calendar would be optimal. (defun planner-index () "Display an index of all known Wiki pages." (interactive) (let ((muse-current-project (muse-project planner-project))) (message "Generating Muse index...") (pop-to-buffer (planner-generate-index)) (goto-char (point-min)) (planner-mode) (message "Generating Muse index...done"))) (defun planner-generate-index (&optional as-list exclude-private) "Generate an index of all Wiki pages. List planner pages separately. If AS-LIST is non-nil, format it as a list. If EXCLUDE-PRIVATE is non-nil, exclude anything for which `muse-project-private-p' returns non-nil." (let ((index (planner-index-as-string as-list exclude-private))) (with-current-buffer (get-buffer-create "*Planner Index*") (erase-buffer) (insert index) (current-buffer)))) (defun planner-index-as-string (&optional as-list exclude-private exclude-daypages) "Generate an index of all Wiki pages. Day pages are listed separately. If AS-LIST is non-nil, format it as a list. If EXCLUDE-PRIVATE is non-nil, exclude anything for which `muse-project-private-p' returns non-nil. If EXCLUDE-DAYPAGES is non-nil, exclude day pages from the list." (let ((index (muse-index-as-string as-list exclude-private))) (with-temp-buffer (insert index) (goto-char (point-min)) (delete-matching-lines "\\[\\[[0-9][0-9][0-9][0-9]\\.[0-9][0-9]\\.[0-9][0-9]\\]\\]") (unless exclude-daypages (goto-char (point-max)) (unless (bolp) (insert "\n")) (if planner-publish-dates-first-p (progn (goto-char (point-min)) (insert "\n") (goto-char (point-min))) (insert "\n")) (let ((dates (mapcar 'car (planner-list-daily-files))) month last-month) (while dates (setq month (substring (car dates) 0 7)) (unless (string= month last-month) (setq last-month month) (insert "\n" month " |")) (insert " [[" (car dates) "][." (substring (car dates) 8) " ]]") (setq dates (cdr dates))) (when planner-publish-dates-first-p (insert "\n")))) (buffer-string)))) ;;;_ + Info (defun planner-annotation-from-info () "If called from an info node, return an annotation. Suitable for use in `planner-annotation-functions'." (when (eq major-mode 'Info-mode) (planner-make-link (concat "info://" Info-current-file "#" Info-current-node) (if (and (not (equal Info-current-file "dir")) (equal Info-current-node "Top")) (file-name-nondirectory Info-current-file) Info-current-node) t))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-info) ;;;_ + Man (defun planner-annotation-from-man () "If called from a man page, return an annotation. Suitable for use in `planner-annotation-functions'." (when (eq major-mode 'Man-mode) ;; There may be a better way to get the name of the current Man page. (let ((page (downcase (cadr (cdar Man-page-list))))) (planner-make-link (concat "man://" page) (concat "Man: " page) t)))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-man) ;;;_ + WoMan (defun planner-annotation-from-woman () "If called from a woman page, return an annotation. Suitable for use in `planner-annotation-functions'." (when (eq major-mode 'woman-mode) ;; You'd think there'd be a better way to get the page name. (let* ((buf (split-string (buffer-name))) (page (substring (nth 2 buf) 0 -1)) (sec (nth 1 buf))) (planner-make-link (concat "woman://" page) (concat "WoMan: " page "(" sec ")") t)))) (custom-add-option 'planner-annotation-functions 'planner-annotation-from-woman) ;;;_ + Common mail functions (defun planner-get-name-from-address (address) "Return the name for ADDRESS to be used in links." (let ((addr (mail-extract-address-components address))) (or (car addr) (cadr addr)))) ;;;_* User functions ;;;_ + Navigation (defun planner-page-file (page &optional no-check-p) "Return a filename if PAGE exists within `planner-project'. If NO-CHECK-P is non-nil, the planner project files are always updated." (muse-project-page-file page planner-project)) ;;;###autoload (defun plan (&optional force-days) "Start your planning for the day, carrying unfinished tasks forward. If FORCE-DAYS is a positive integer, search that many days in the past for unfinished tasks. If FORCE-DAYS is 0 or t, scan all days. If FORCE-DAYS is nil, use the value of `planner-carry-tasks-forward' instead, except t means scan only yesterday." ;; Special treatment of t for planner-carry-tasks-forward is for ;; backward compatibility. (interactive "P") (unless muse-project-alist (planner-display-warning (concat "The variable `muse-project-alist' has not defined.\n" "\nSee the \"Creating Your Planner\" chapter in the Planner" " manual\nfor details on how to set this up.")) (error "The variable `muse-project-alist' has not been defined")) (if planner-use-day-pages (progn (unless force-days (setq force-days (if (equal planner-carry-tasks-forward t) 1 planner-carry-tasks-forward))) (when (and (integerp force-days) (= force-days 0)) (setq force-days t)) (planner-goto-today) (let* ((today (planner-today)) (names (planner-get-day-pages nil (planner-yesterday))) (today-buffer (current-buffer)) (planner-tasks-file-behavior ;; Force saving so that the file list can be updated (or planner-tasks-file-behavior 'save)) (planner-use-other-window nil) (live-buffers (and (equal planner-tasks-file-behavior 'close) (buffer-list)))) ;; Limit the list for force-days (when (and (integerp force-days) (> (length names) force-days)) (setcdr (nthcdr (1- force-days) names) nil)) (when force-days (while names (find-file (cdar names)) ;; Attempt to copy all the tasks (when (not (equal today (planner-page-name))) (let ((planner-tasks-file-behavior nil)) (save-restriction (planner-narrow-to-section 'tasks) (planner-copy-or-move-region (point-min) (point-max) (planner-today) t))) (unless (buffer-modified-p) (kill-buffer (current-buffer)))) (setq names (cdr names)))) ;; Jump to the most recent daily page (if (or planner-carry-tasks-forward (planner-page-file today) (null names)) (planner-goto-today) (planner-goto (caar names))) ;; Save/kill files if configured to do so (when planner-tasks-file-behavior (planner-save-buffers live-buffers)))) (planner-find-file (or planner-default-page planner-initial-page)))) (defvar planner-goto-hook '(planner-seek-to-first) "Functions called after a planner day page is opened.") ;;;###autoload (defun planner-goto (date &optional just-show) "Jump to the planning page for DATE. If no page for DATE exists and JUST-SHOW is non-nil, don't create a new page - simply return nil." (interactive (list (or (planner-read-date) (planner-read-non-date-page (planner-file-alist))))) (if (or (not just-show) (planner-page-exists-p date)) (progn (planner-find-file date (if planner-use-other-window 'find-file-other-window 'find-file)) (widen) (goto-char (point-min)) (run-hooks 'planner-goto-hook) ;; planner-goto-hook returns nil t) ;; File not found, and not supposed to be created. (when (interactive-p) (message "No planner file for %s." date)) ;; return nil nil)) ;;;###autoload (defun planner-goto-plan-page (page) "Opens PAGE in the the `planner-project' wiki. Use `planner-goto' if you want fancy calendar completion." (interactive (list (planner-read-name (planner-file-alist)))) (planner-find-file page)) ;;;###autoload (defun planner-show (date) "Show the plan page for DATE in another window, but don't select it. If no page for DATE exists, return nil." (interactive (list (planner-read-date))) (save-selected-window (let ((planner-use-other-window t)) (planner-goto date planner-show-only-existing)))) ;;;###autoload (defun planner-goto-today () "Jump to the planning page for today." (interactive) (planner-goto (planner-today))) ;;;###autoload (defun planner-goto-most-recent () "Go to the most recent day with planning info." (interactive) (planner-goto (planner-get-previous-existing-day (planner-calculate-date-from-day-offset (planner-get-current-date-filename) 1)))) ;;;###autoload (defun planner-goto-yesterday (&optional days) "Goto the planner page DAYS before the currently displayed date. If DAYS is nil, goes to the day immediately before the currently displayed date. If the current buffer is not a daily planner page, calculates date based on today." (interactive "p") (let ((planner-use-other-window nil)) (planner-goto (planner-calculate-date-from-day-offset (planner-get-current-date-filename) (or (- days) -1))))) ;;;###autoload (defun planner-goto-tomorrow (&optional days) "Goto the planner page DAYS after the currently displayed date. If DAYS is nil, goes to the day immediately after the currently displayed date. If the current buffer is not a daily planner page, calculates date based on today." (interactive "p") (let ((planner-use-other-window nil)) (planner-goto (planner-calculate-date-from-day-offset (planner-get-current-date-filename) (or days 1))))) ;;;###autoload (defun planner-goto-previous-daily-page () "Goto the last plan page before the current date. The current date is taken from the day page in the current buffer, or today if the current buffer is not a planner page. Does not create pages if they do not yet exist." (interactive) (let ((planner-use-other-window nil)) (planner-goto (planner-get-previous-existing-day (planner-get-current-date-filename))))) ;;;###autoload (defun planner-goto-next-daily-page () "Goto the first plan page after the current date. The current date is taken from the day page in the current buffer, or today if the current buffer is not a planner page. Does not create pages if they do not yet exist." (interactive) (let ((planner-use-other-window nil)) (planner-goto (planner-get-next-existing-day (planner-get-current-date-filename))))) ;;;_ + Tasks ;;;_ + Creating ;;;###autoload (defun planner-create-high-priority-task-from-buffer () "Create a high-priority task based on this buffer. Do not use this in LISP programs. Instead, set the value of `planner-default-task-priority' and call `planner-create-task' or `planner-create-task-from-buffer'." (interactive) (let ((planner-default-task-priority "A")) (call-interactively 'planner-create-task-from-buffer))) ;;;###autoload (defun planner-create-medium-priority-task-from-buffer () "Create a high-priority task based on this buffer. Do not use this in LISP programs. Instead, set the value of `planner-default-task-priority' and call `planner-create-task' or `planner-create-task-from-buffer'." (interactive) (let ((planner-default-task-priority "B")) (call-interactively 'planner-create-task-from-buffer))) ;;;###autoload (defun planner-create-low-priority-task-from-buffer () "Create a high-priority task based on this buffer. Do not use this in LISP programs. Instead, set the value of `planner-default-task-priority' and call `planner-create-task' or `planner-create-task-from-buffer'." (interactive) (let ((planner-default-task-priority "C")) (call-interactively 'planner-create-task-from-buffer))) (defun planner-read-task () "Return a list of information for a task." (list (read-string "Describe task: ") (when planner-use-day-pages (cond ;; Universal prefix means pick up from current page ((and current-prefix-arg (planner-derived-mode-p 'planner-mode) (string-match planner-date-regexp (planner-page-name))) (planner-page-name)) ;; Date selected in calendar ((condition-case nil (calendar-cursor-to-date) (error nil)) (planner-date-to-filename (calendar-cursor-to-date))) ;; Prompt for date (t (let ((planner-expand-name-favor-future-p (or planner-expand-name-favor-future-p planner-task-dates-favor-future-p))) (planner-read-date))))) (when planner-use-plan-pages (if (and current-prefix-arg (planner-derived-mode-p 'planner-mode) (not (string-match planner-date-regexp (planner-page-name)))) ;; Universal prefix means pick up from current page (planner-page-name) (let ((planner-default-page (if (and (planner-derived-mode-p 'planner-mode) (planner-page-name) (not (string-match planner-date-regexp (planner-page-name)))) (planner-page-name) planner-default-page))) (planner-read-non-date-page (planner-file-alist))))) planner-default-task-status)) ;; NOTE: Prefix arg changed to prompt for PLAN-PAGE instead of ;; set to today ;;;###autoload (defun planner-create-task-from-buffer (title date &optional plan-page status) "Create a new task named TITLE on DATE based on the current buffer. With a prefix, do not prompt for PLAN-PAGE. The task is associated with PLAN-PAGE if non-nil. If STATUS is non-nil, use that as the status for the task. Otherwise, use `planner-default-task-status'. See `planner-create-task' for more information." (interactive (planner-read-task)) (setq planner-default-page plan-page) (let ((planner-create-task-hook (append planner-create-task-from-buffer-hook planner-create-task-hook)) (annotation (run-hook-with-args-until-success 'planner-annotation-functions))) (when (and planner-annotation-symbol-string (string-match planner-annotation-symbol-string title)) (setq title (replace-match (or annotation "") t t title) annotation nil)) (planner-create-task title (when (and date (string-match planner-date-regexp date)) date) annotation plan-page status))) (defun planner-create-task (title date &optional annotation plan-page status) "Create a new task named TITLE based on the current Wiki page. If DATE is non-nil, makes a daily entry on DATE, else makes an entry in today's planner page. It's assumed that the current Wiki page is the page you're using to plan an activity. Any time accrued to this task will be applied to that page's name in the timelog file, assuming you use timeclock. If ANNOTATION is non-nil, it will be used for the page annotation. If PLAN-PAGE is non-nil, the task is associated with the given page. If STATUS is non-nil, use that as the status for the task. Otherwise, use `planner-default-task-status'. If called with an interactive prefix argument, do not prompt for PLAN-PAGE. You probably want to call `planner-create-task-from-buffer' instead." (interactive (list (read-string "Describe task: ") (when planner-use-day-pages (cond ;; Universal prefix means pick up from current page ((and current-prefix-arg (planner-derived-mode-p 'planner-mode) (string-match planner-date-regexp (planner-page-name))) (planner-page-name)) ;; Date selected in calendar ((condition-case nil (calendar-cursor-to-date) (error nil)) (planner-date-to-filename (calendar-cursor-to-date))) ;; Prompt for date (t (let ((planner-expand-name-favor-future-p (or planner-expand-name-favor-future-p planner-task-dates-favor-future-p))) (planner-read-date))))) nil ;; No annotation, interactively (when planner-use-plan-pages (if (and current-prefix-arg (planner-derived-mode-p 'planner-mode) (not (string-match planner-date-regexp (planner-page-name)))) ;; Universal prefix means pick up from current page (planner-page-name) (let ((planner-default-page (if (and (planner-derived-mode-p 'planner-mode) (planner-page-name) (not (string-match planner-date-regexp (planner-page-name)))) (planner-page-name) planner-default-page))) (planner-read-non-date-page (planner-file-alist))))) planner-default-task-status)) (setq planner-default-page plan-page) (planner-create-task-from-info nil ; info planner-default-task-priority ; priority "0" ; number (or status planner-default-task-status) ; status (if (and annotation (not (string= annotation "")) (or (not plan-page) (and (not (string= plan-page annotation)) (not (string= (concat "[[" plan-page "]]") annotation))))) ;; Used C-u to make a plan-page annotation, so preserve ;; the context (concat title " : " annotation) title) ; description ;; link: If creating this from a planner plan page, use the ;; current page name (and plan-page (planner-make-link plan-page)) ; link text date plan-page)) (defun planner-create-task-from-note (title date &optional plan-page status) "Create a task based on the current note with TITLE, DATE, PLAN-PAGE and STATUS. A more do-what-I-mean way to do this is to position point on the first line of a note (.#1 ...) and call `planner-create-task-from-buffer'." (interactive (let* ((info (planner-current-note-info)) (planner-default-page (and info (planner-note-plan info)))) (if info (planner-read-task) (error "Not in a planner note")))) (let* ((info (planner-current-note-info)) (annotation (planner-make-link (concat (planner-note-page info) "#" (planner-note-anchor info))))) (when (and planner-annotation-symbol-string (string-match planner-annotation-symbol-string title)) (setq title (replace-match (or annotation "") t t title) annotation nil)) (planner-create-task title (when (and date (string-match planner-date-regexp date)) date) annotation plan-page status))) ;;;_ + Rescheduling (defvar planner-copy-or-move-task-suppress-duplicates t "*If non-nil, do not create duplicate tasks.") (defun planner-replan-task-basic (page-name) "Change or assign the plan page for the current task. PAGE-NAME is the new plan page for the task. Use `planner-copy-or-move-task' if you want to change the date. With a prefix, provide the current link text for editing." (interactive (list (planner-read-name (planner-file-alist) nil (when current-prefix-arg (planner-task-plan (planner-current-task-info)))))) (let ((info (planner-current-task-info))) (when (and info (not (equal page-name (planner-task-plan info)))) (with-planner-update-setup ;; Delete from old plan page (when (planner-task-plan info) (planner-find-file (planner-task-plan info)) (when (planner-find-task info) (delete-region (planner-line-beginning-position) (1+ (planner-line-end-position))))) ;; Add to new plan page, if any, and update date (if page-name (progn (planner-find-file page-name) (planner-seek-task-creation-point) (insert (planner-format-task info nil nil nil nil (or (planner-task-date info) "") (or (planner-task-date info) "")) "\n") (forward-line -1) (planner-update-task)) ;; Else, go to day page and update line (planner-find-file (planner-task-date info)) (if (planner-find-task info) (delete-region (planner-line-beginning-position) (1+ (planner-line-end-position))) (planner-seek-task-creation-point)) (insert (planner-format-task info nil nil nil nil (or (planner-make-link page-name) "") (or page-name "")) "\n")))))) (defalias 'planner-replan-task 'planner-replan-task-basic) (defun planner-seek-task-creation-point () "Jump to point where task would be created." (planner-seek-to-first (cdr (assoc 'tasks planner-sections))) (when planner-add-task-at-end-flag (while (looking-at "^#") (forward-line)) (unless (bolp) (insert "\n")))) (defun planner-copy-or-move-task-basic (&optional date force) "Move the current task to DATE. If this is the original task, it copies it instead of moving. Most of the time, the original should be kept in a planning file, but this is not required. If FORCE is non-nil, the task is moved regardless of status. It also works for creating tasks from a Note. Use `planner-replan-task' if you want to change the plan page in order to get better completion. This function is the most complex aspect of planner.el." (interactive (list (let ((planner-expand-name-favor-future-p (or planner-expand-name-favor-future-p planner-task-dates-favor-future-p))) (planner-read-date)) current-prefix-arg)) (if (or (null date) (string-match planner-date-regexp date)) (let ((live-buffers (when (equal planner-tasks-file-behavior 'close) (buffer-list)))) (when (equal date (planner-page-name)) (error "Cannot move a task back to the same day")) (save-excursion (save-window-excursion (save-restriction (beginning-of-line) (let* ((task-info (planner-current-task-info)) (plan-page (planner-task-plan task-info)) (date-page (planner-task-date task-info))) (unless task-info (error "There is no task on the current line")) (unless force (when (equal date-page date) (error "Cannot move a task back to the same day")) (when (equal (planner-task-status task-info) "X") (error "Cannot reschedule a completed task")) (when (equal (planner-task-status task-info) "C") (error "Cannot reschedule a cancelled task"))) (when (and (or (null date) (string= date "nil")) (not plan-page)) (error "Cannot unset date in task not associated with plan")) ;; Delete it from the old date page (when date-page (planner-goto date-page) (goto-char (point-min)) (when (planner-find-task task-info) (beginning-of-line) (delete-region (point) (min (point-max) (1+ (planner-line-end-position)))))) ;; Update the new date page (unless (null date) (planner-goto date) (when (or (not planner-copy-or-move-task-suppress-duplicates) (and (not (planner-find-task task-info)))) (planner-seek-task-creation-point) (insert (planner-format-task task-info nil nil nil nil (when plan-page (planner-make-link plan-page))) "\n"))) ;; Update planner page (when (and plan-page (not (string-match planner-date-regexp plan-page))) (planner-find-file plan-page) (goto-char (point-min)) (if (planner-find-task task-info) (progn (beginning-of-line) (delete-region (point) (min (point-max) (1+ (planner-line-end-position))))) (planner-seek-task-creation-point)) (insert (planner-format-task task-info nil nil nil nil (planner-make-link date)) "\n")) t)))) ;; Operation successful. (when planner-tasks-file-behavior (planner-save-buffers live-buffers t))) (when (planner-replan-task date) t))) (defalias 'planner-copy-or-move-task 'planner-copy-or-move-task-basic) ;;;_ + Deleting (defcustom planner-delete-task-hook nil "Hook called after a task has been deleted. Argument is a task information list. If a function returns nil, no other functions will be processed." :type 'hook :group 'planner-tasks) (defun planner-delete-task () "Deletes this task from the current page and the linked page." (interactive) (save-excursion (save-window-excursion (beginning-of-line) (let* ((task-info (planner-current-task-info)) (task-link (and task-info (planner-task-link task-info))) (live-buffers (and (equal planner-tasks-file-behavior 'close) (buffer-list)))) (unless task-info (error "There is no task on the current line")) (beginning-of-line) (delete-region (point) (min (point-max) (1+ (planner-line-end-position)))) (when (and task-link (assoc task-link (planner-file-alist)) (planner-jump-to-linked-task task-info)) (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position))))) (when planner-tasks-file-behavior (planner-save-buffers live-buffers t)) (run-hook-with-args-until-failure 'planner-delete-task-hook task-info))))) ;;;_ + Updating (defun planner-edit-task-description-basic (description) "Change the current task to use DESCRIPTION." (interactive (list (let* ((info (planner-current-task-info)) (planner-task-history (list (planner-task-description info)))) (unless info (error "No task on current line")) (read-string "New description: " (cons (planner-task-description info) 1) '(planner-task-history . 1) (planner-task-description info))))) (let ((point (point))) (with-planner-update-setup (let ((info (planner-current-task-info)) (live-buffers (and (equal planner-tasks-file-behavior 'close) (buffer-list)))) (delete-region (planner-line-beginning-position) (planner-line-end-position)) (insert (planner-format-task info nil nil nil description)) (when (planner-task-link info) (if (planner-jump-to-linked-task info) (progn (setq info (planner-current-task-info)) (delete-region (planner-line-beginning-position) (planner-line-end-position)) (insert (planner-format-task info nil nil nil description))) (planner-seek-task-creation-point) (insert (planner-format-task info nil nil nil description (planner-make-link (planner-task-page info))) "\n"))))) (goto-char (point)))) (defalias 'planner-edit-task-description 'planner-edit-task-description-basic) (defun planner-update-task-basic () "Update the current task's priority and status on the linked page. Tasks are considered the same if they have the same description. This function allows you to force a task to be recreated if it disappeared from the associated page. Note that the text of the task must not change. If you want to be able to update the task description, see planner-id.el." (interactive) (with-planner-update-setup (beginning-of-line) (let* ((task-info (planner-current-task-info)) (task-link (and task-info (if (string-match planner-date-regexp (planner-page-name)) (planner-task-plan task-info) (planner-task-date task-info)))) (original (planner-page-name))) (unless task-info (error "There is no task on the current line")) ;; (unless task-link ;; (error "There is no link for the current task")) (if (planner-jump-to-linked-task task-info) ;; Already there, so update only if changed (unless (planner-tasks-equal-p task-info (planner-current-task-info)) (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position)))) (insert (planner-format-task task-info nil nil nil nil (planner-make-link original)) "\n")) ;; Not yet there, so add it (when (planner-local-page-p task-link) (planner-find-file task-link) (save-excursion (save-restriction (planner-seek-task-creation-point) (insert (planner-format-task task-info nil nil nil nil (planner-make-link original)) "\n")))))))) (defalias 'planner-update-task 'planner-update-task-basic) ;;;_ + Prioritizing ;; This really should be called planner-raise/lower-task-priority, but ;; for some obscure reason, the original planner.el called the task ;; numbers priorities and "A/B/C" categories. I'm not really sure if I ;; can change the name right now. I suppose we eventually should. (defun planner-set-task-priority (priority) "Set the priority of the current task. This changes a low-priority task to a medium-priority task and a medium-priority task to a high-priority task." (let ((info (planner-current-task-info))) (when info (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position)))) (save-excursion (insert (planner-format-task info priority) "\n")) (when (planner-task-link info) (planner-update-task))))) (defun planner-raise-task-priority () "Raise the priority of the current task. This changes a low-priority task to a medium-priority task and a medium-priority task to a high-priority task." (interactive) (let ((info (planner-current-task-info))) (when info (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position)))) (save-excursion (insert (planner-format-task info (cond ((string= "A" (planner-task-priority info)) "A") ((string= "B" (planner-task-priority info)) "A") ((string= "C" (planner-task-priority info)) "B") (t "C"))) "\n")) (when (planner-task-link info) (planner-update-task))))) (defun planner-lower-task-priority () "Lower the priority of the current task. This changes a medium-priority task to a low-priority task and a high-priority task to a low-priority task." (interactive) (let ((info (planner-current-task-info))) (when info (delete-region (planner-line-beginning-position) (min (point-max) (1+ (planner-line-end-position)))) (save-excursion (insert (planner-format-task info (cond ((string= "A" (planner-task-priority info)) "B") ((string= "B" (planner-task-priority info)) "C") (t "C"))) "\n")) (when (planner-task-link info) (planner-update-task))))) (defun planner-raise-task (&optional arg) "Raise the number of the current task by ARG steps. (Default: 1)" (interactive "p") (beginning-of-line) (setq arg (or arg 1)) ; ARG defaults to 1 if not specified (if (< arg 0) (planner-lower-task (- arg))) (let* ((current-task (planner-current-task-info)) ;; task-seen will be the last task moved over with the same link task-seen) (unless current-task (error "Not on a task line")) ;; Store the current line in the kill ring, deleting it (kill-region (point) (1+ (planner-line-end-position))) ;; If the previous line is not a task, search for the previous block (while (> arg 0) (let ((old-point (point))) (if (= (forward-line -1) 0) (if (not (planner-current-task-info)) (if (re-search-backward "^#[ABC][0-9]*[ \t]" nil t) (beginning-of-line) (setq arg -1) ;; Stop moving, yank back at current place. (goto-char old-point))) (setq arg -1)) ;; Stop moving, yank back at current place. (when (and (> arg 0) (string= (planner-task-plan current-task) (planner-task-plan (planner-current-task-info)))) (setq task-seen (planner-current-task-info)))) (setq arg (1- arg))) ;; Cursor now at right place (save-excursion (yank)) ;; Update the linked page, if any (save-window-excursion (save-excursion (save-restriction (when (and task-seen (planner-task-link current-task) (planner-jump-to-linked-task current-task)) (let ((old-task (buffer-substring (planner-line-beginning-position) (planner-line-end-position))) found) (save-excursion (save-restriction (when (planner-find-task task-seen) ;; Found the new task, so delete the old task and ;; insert here (setq found t) (insert old-task "\n")))) (when found (delete-region (planner-line-beginning-position) (1+ (planner-line-end-position))))))))))) (defun planner-lower-task (&optional arg) "Lower the number of the current task by ARG steps (default 1)." (interactive "p") (beginning-of-line) (setq arg (or arg 1)) ; ARG defaults to 1 if not specified (if (< arg 0) (planner-raise-task (- arg))) (let* ((current-task (planner-current-task-info)) ;; task-seen will be the last task moved over with the same link task-seen) (unless current-task (error "Not on a task line")) ;; Store the current line in the kill ring, deleting it (kill-region (point) (1+ (planner-line-end-position))) ;; If the current line is not a task, search for the next block (while (> arg 0) (let ((old-point (point))) (if (not (planner-current-task-info)) (if (re-search-forward "^#[ABC][0-9]*[ \t]" nil t) (planner-line-beginning-position) (setq arg -1) ;; Stop moving, yank back at current place. (goto-char old-point))) (when (and (> arg 0) (string= (planner-task-plan current-task) (planner-task-plan (planner-current-task-info)))) (setq task-seen (planner-current-task-info)))) (unless (and (> arg 0) (= (forward-line 1) 0)) (setq arg -1)) (setq arg (1- arg))) ;; Cursor now at right place (save-excursion (yank)) ;; Update the linked page, if any (save-window-excursion (save-excursion (save-restriction (when (and task-seen (planner-task-link current-task) (planner-jump-to-linked-task current-task)) (let ((old-task (buffer-substring (planner-line-beginning-position) (planner-line-end-position))) found) (save-excursion (save-restriction (when (planner-find-task task-seen) ;; Found the new task, so delete the old task and ;; insert here (setq found t) (forward-line 1) (insert old-task "\n")))) (when found (delete-region (planner-line-beginning-position) (1+ (planner-line-end-position))))))))))) ;;;_ + Changing the status (defvar planner-mark-task-hook nil "Hook called after a task's status has been changed. Arguments are OLD-STATUS and NEW-STATUS. Functions should leave the point on the task. If a function returns nil, no other functions will be processed.") (defun planner-mark-task (mark &optional this-only) "Change task status to MARK. If THIS-ONLY is non-nil, the linked planner page is not updated." (let ((case-fold-search nil) (info (planner-current-task-info))) (when info (with-planner-update-setup (goto-char (planner-line-beginning-position)) (skip-chars-forward "^ \t" (planner-line-end-position)) (skip-chars-forward " \t" (planner-line-end-position)) (delete-char 1) (insert mark) (unless this-only (planner-update-task)) (run-hook-with-args-until-failure 'planner-mark-task-hook (planner-task-status info) mark))))) (defun planner-task-open () "Mark the current task as open." (interactive) (planner-mark-task "_")) (defun planner-task-in-progress () "Mark the current task as in progress." (interactive) (planner-mark-task "o")) (defun planner-task-done () "Mark the current task as done." (interactive) (planner-mark-task "X")) (defun planner-task-cancelled () "Mark the current task as cancelled." (interactive) (planner-mark-task "C")) (defun planner-task-delegated () "Mark the current task as delegated." (interactive) (planner-mark-task "D")) (defun planner-task-pending () "Mark the current task as pending." (interactive) (planner-mark-task "P")) ;;;_ + Extracting (defun planner-seek-next-unfinished-task () "Move point to the next unfinished task on this page. Return nil if not found." (interactive) (re-search-forward "^#[A-C][0-9]*\\s-+[_oDP]\\s-+" nil t)) (defun planner-list-tasks-with-status (status &optional pages) "Display all tasks that match the STATUS regular expression on all day pages. If PAGES is: t: check all pages nil: check all day pages regexp: search all pages whose filenames match the regexp list of page names: limit to those pages alist of page/filename: limit to those pages This could take a long time." (interactive (list (read-string "Status: "))) (set-buffer (get-buffer-create "*Planner Tasks*")) (erase-buffer) (let (tasks) (setq tasks (planner-extract-tasks (cond ((eq pages t) (planner-file-alist)) ((eq pages nil) (planner-get-day-pages)) ((not (listp pages)) (let ((regexp pages)) (setq pages nil) (dolist (page (planner-file-alist)) (when (string-match regexp (cdr page)) (setq pages (cons page pages))))) pages) (t pages)) (lambda (item) (string-match status (planner-task-status item))))) (while tasks (insert (format "[[%s]] %s %s %s\n" (planner-task-page (car tasks)) (planner-task-priority (car tasks)) (planner-task-status (car tasks)) (planner-task-description (car tasks)))) (setq tasks (cdr tasks)))) (planner-mode) (setq muse-current-project (muse-project planner-project)) (goto-char (point-min)) (pop-to-buffer (current-buffer))) (defun planner-list-unfinished-tasks (&optional pages) "Display all unfinished tasks on PAGES. The PAGES argument limits the pages to be checked in this manner: t: check all pages \"regexp\": search all pages whose filenames match \"regexp\" list of page names: limit to those pages alist of page/filenames: limit to those pages Called interactively, this function will search day pages by default. You can specify the start and end dates or leave them as nil to search all days. Calling this function with an interactive prefix will prompt for a regular expression to limit pages. Specify \".\" or leave this blank to include all pages." (interactive (list (if current-prefix-arg (read-string "Regexp: ") (let ((planner-expand-name-default "nil")) (planner-get-day-pages (planner-read-date "nil by default. Start") (planner-read-date "nil by default. End") t))))) (planner-list-tasks-with-status "[^XC\n]" pages)) ;;;_ + Notes (defvar planner-search-notes-buffer "*Planner Search*" "Buffer for search results.") ;;;###autoload (defun planner-search-notes-with-body (regexp limit) "Return a buffer with all the notes returned by the query for REGEXP. If called with a prefix argument, prompt for LIMIT and search days on or after LIMIT. Display the body of the notes as well." (interactive (list (read-string "Regexp: ") (if current-prefix-arg (let ((planner-expand-name-favor-future-p nil)) (planner-read-date))))) (planner-search-notes regexp limit t)) ;;;###autoload (defun planner-search-notes (regexp limit &optional include-body) "Return a buffer with all the notes returned by the query for REGEXP. If called with a prefix argument, prompt for LIMIT and search days on or after LIMIT. If INCLUDE-BODY is non-nil, return the body as well." (interactive (list (read-string "Regexp: ") (if current-prefix-arg (let ((planner-expand-name-favor-future-p nil)) (planner-read-date))) nil)) (with-planner (let* ((case-fold-search t) (results (planner-search-notes-internal regexp limit include-body))) (if results (progn (set-buffer (get-buffer-create planner-search-notes-buffer)) (setq buffer-read-only nil) (erase-buffer) (mapcar (if include-body (lambda (item) (insert "** " (planner-make-link (elt item 0) (elt item 1)) "\t" (elt item 3) "\n\n")) (lambda (item) (insert (planner-make-link (elt item 0) (elt item 1)) "\t" (elt item 2) "\n"))) results) (planner-mode) (goto-char (point-min)) (pop-to-buffer (current-buffer))) (message "No results found."))))) ;;;_ + Calendar (defun planner-calendar-insinuate () "Hook Planner into Calendar. Adds special planner key bindings to `calendar-mode-map'. After this function is evaluated, you can use the following planner-related keybindings in `calendar-mode-map': n jump to the planner page for the current day. N display the planner page for the current day." (interactive) (require 'calendar) (add-hook 'calendar-move-hook (lambda () (when planner-calendar-show-planner-files (planner-calendar-show)))) (define-key calendar-mode-map "n" 'planner-calendar-goto) (define-key calendar-mode-map "N" 'planner-calendar-show)) (defalias 'planner-insinuate-calendar 'planner-calendar-insinuate) (defvar planner-calendar-buffer-list nil "List of buffers opened by calendar.") (defun planner-kill-calendar-files () "Remove planner files shown from Calendar." (interactive) (while planner-calendar-buffer-list (when (buffer-live-p (car planner-calendar-buffer-list)) (with-current-buffer (car planner-calendar-buffer-list) (save-buffer) (planner-maybe-remove-file))) (setq planner-calendar-buffer-list (cdr planner-calendar-buffer-list)))) ;;;###autoload (defun planner-calendar-goto () "Goto the plan page corresponding to the calendar date." (interactive) (let ((planner-use-other-window t)) (planner-goto (planner-date-to-filename (calendar-cursor-to-date))))) ;;;###autoload (defun planner-calendar-show () "Show the plan page for the calendar date under point in another window." (interactive) (save-selected-window (let ((planner-use-other-window t) (date (planner-date-to-filename (calendar-cursor-to-date)))) (if (planner-goto date planner-show-only-existing) (add-to-list 'planner-calendar-buffer-list (current-buffer)) ;; Return nil or a message if there is no day plan page. planner-goto ;; is not called interactively, so it doesn't send a message. (when (interactive-p) (message "No planner file for %s" date)) ;; return nil nil)))) (defadvice exit-calendar (after planner activate protect) "Call `planner-kill-calendar-files'." (planner-kill-calendar-files)) (defun planner-calendar-select () "Return to `planner-read-date' with the date currently selected." (interactive) (when (calendar-cursor-to-date) (setq planner-calendar-selected-date (planner-date-to-filename (calendar-cursor-to-date))) (if (active-minibuffer-window) (exit-minibuffer)))) ;;;_* Context-sensitive keybindings (defun planner-jump-to-link () "Jump to the item linked to by the current item." (interactive) (cond ((planner-current-task-info) (planner-jump-to-linked-task)) ((planner-current-note-info) (planner-jump-to-linked-note)))) (defun planner-move-up () "Move up. Task: Raise the number of the current task. Note: Renumbering does not make sense for notes right now, so go to the previous note. Headline: Go to previous headline of the same depth." (interactive) (cond ((planner-current-task-info) (planner-raise-task)) ((planner-current-note-info) (re-search-backward "^\\.#[0-9]+" nil t)) ((and (goto-char (planner-line-beginning-position)) (looking-at "^\\*+")) (re-search-backward (concat "^" (regexp-quote (match-string 0)) "\\s-") nil t)))) (defun planner-move-down () "Move down. Task: Lower the number of the current task. Note: Renumbering does not make sense for notes right now, so go to the next note. Headline: Go to the next headline of the same depth." (interactive) (cond ((planner-current-task-info) (planner-lower-task)) ((planner-current-note-info) (forward-line 1) (re-search-forward "^\\.#[0-9]+" nil t)) ((and (goto-char (planner-line-beginning-position)) (looking-at "^\\*+")) (forward-line 1) (re-search-forward (concat "^" (regexp-quote (match-string 0)) "\\s-") nil t)))) ;;;_* Initialization (setq planner-loaded t) ;; Insinuate with allout mode (add-hook 'allout-mode-leaders '(planner-mode . ".")) (provide 'planner) ;;;_* Local emacs vars. ;; Local variables: ;; allout-layout: (* 0 : ) ;; End: ;;; planner.el ends here planner-el/planner2diary.py000066400000000000000000000222541226462314700162530ustar00rootroot00000000000000#!/usr/bin/python # Copyright (C) 2001, 2008 Free Software Foundation, Inc. # Author: John Wiegley import os, os.path, sys, re, time, string def IsLeapYear(year): if year % 4 == 0: if year % 100 == 0: if year % 400 == 0: return 1 else: return 0 else: return 1 else: return 0 def NumberDaysYear(year): return 365 + IsLeapYear(year) def NumberDaysMonth(month = None, year = None): if month is None: m = time.localtime()[1] else: m = month if year is None: y = time.localtime()[0] else: y = year if m == 2: if IsLeapYear(y): return 29 else: return 28 elif m in (1, 3, 5, 7, 8, 10, 12): return 31 else: return 30 class Date(object): """The Date class.""" Weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] Months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] #The slots in a Date object are constrained to allow more efficient operations. __slots__ = ["year", "month", "day"] def __init__(self, tm = None): """The initializer has an optional argument, time, in the time module format, wether as in seconds since the epoch (Unix time) wether as a tuple (time tuple). If it is not provided, then it returns the current date.""" if tm is None: t = time.localtime() else: if isinstance(tm, int): t = time.localtime(tm) else: t = tm self.year, self.month, self.day = t[:3] def weekday(self): """Returns the weekday of the date. The format is as in the time module: Monday is 0 and sunday is 6.""" a = (14 - self.month)//12 y = self.year - a m = self.month + 12*a -2 d = (self.day + y + y//4 - y//100 + y//400 + (31*m//12))%7 if d: ret = d - 1 else: ret = 6 return ret def __str__(self): return "%s, %d-%s-%d" % (Date.Weekdays[self.weekday()], self.day, Date.Months[self.month - 1], self.year) def copy(self): """Deep copy of Date objects.""" ret = Date() ret.year, ret.month, ret.day = self.year, self.month, self.day return ret #The iterator protocol. The iteration is "destructive", like in files. def __iter__(self): return self def next(self): #Last day of the month. if self.day == NumberDaysMonth(self.month, self.year): self.day = 1 #December case. if self.month == 12: self.month = 1 self.year += 1 else: self.month += 1 else: self.day += 1 #Extended iterator protocol. One can go backwards. def previous(self): #First day of the month. if self.day == 1: #January case. if self.month == 1: self.month = 12 self.year -= 1 else: self.month -= 1 self.day = NumberDaysMonth(self.month, self.year) else: self.day -= 1 #Comparison methods. def __eq__(self, date): return self.year == date.year and self.month == date.month and\ self.day == date.day def __lt__(self, other): return (self.year, self.month, self.day) < (other.year, other.month, other.day) def __le__(self, other): return (self.year, self.month, self.day) <= (other.year, other.month, other.day) #Dates can be used as keys in dictionaries. def __hash__(self): return hash((self.year, self.month, self.day)) #Some useful methods. def GetYearDay(self): """Returns the year day of a date.""" ret = self.day for month in range(1, self.month): ret += NumberDaysMonth(month, self.year) return ret def DaysToEndYear(self): """Returns the number of days until the end of the year.""" ret = NumberDaysMonth(self.month, self.year) - self.day for i in range(self.month + 1, 13): ret += NumberDaysMonth(i, self.year) return ret def GetWeekday(self): """Returns the weekday of the date in string format.""" return Date.Weekdays[self.weekday()] def GetMonth(self): """Returns the month of the date in string format.""" return Date.Months[self.month - 1] def ToJDNumber(self): """Returns the Julian day number of a date.""" a = (14 - self.month)//12 y = self.year + 4800 - a m = self.month + 12*a - 3 return self.day + ((153*m + 2)//5) + 365*y + y//4 - y//100 + y//400 - 32045 #Binary operations. def __add__(self, n): """Adds a (signed) number of days to the date.""" if isinstance(n, int): #Calculate julian day number and add n. temp = self.ToJDNumber() + n #Convert back to date format. return DateFromJDNumber(temp) else: raise TypeError, "%s is not an integer." % str(n) def __sub__(self, date): """Returns the (signed) difference of days between the dates.""" #If it is an integer defer calculation to the __add__ method. if isinstance(date, int): return self.__add__(-date) elif isinstance(date, Date): #Case: The years are equal. if self.year == date.year: return self.GetYearDay() - date.GetYearDay() else: if self < date: ret = self.DaysToEndYear() + date.GetYearDay() for year in range(self.year + 1, date.year): ret += NumberDaysYear(year) return -ret else: ret = date.DaysToEndYear() + self.GetYearDay() for year in range(date.year + 1, self.year): ret += NumberDaysYear(year) return ret else: raise TypeError, "%s is neither an integer nor a Date." % str(date) #Adding an integer is "commutative". def __radd__(self, n): return self.__add__(n) #Conversion methods. def ToTimeTuple(self): """Convert a date into a time tuple (time module) corresponding to the same day with the midnight hour.""" ret = [self.year, self.month, self.day] ret.extend([0, 0, 0]) ret.append(self.weekday()) ret.extend([self.GetYearDay(), 0]) return tuple(ret) def needparsep(fname): import re import time curdate = Date() if re.search("^([0-9]{4})\.([0-9]+)\.([0-9]+)$", fname): if curdate <= Date(time.strptime(fname, "%Y.%m.%d")): return True else: return False else: return False def needtransferp(line): import re if re.search("^\s*([0-9]+:[0-9]+)\s*(.+)", line): return True else: return False if __name__ == "__main__": try: dirname = sys.argv[1] except IndexError: dirname = "~/emacs/plans" filelist = filter(needparsep, os.listdir(os.path.expanduser(dirname))) selected = [] for filename in filelist: thatdate = Date(time.strptime(filename, "%Y.%m.%d")) thatdate = repr(thatdate.month)+"/"+repr(thatdate.day)+"/"+repr(thatdate.year) selected = filter(needtransferp, open(os.path.join(os.path.expanduser(dirname), filename), "r")) for line in selected: m = re.search("^\s*([0-9]+:[0-9]+)\s*\|\s*([0-9]+:[0-9]+)\s*\|\s*(.+)", line) if m: outputstr = thatdate+" "+m.group(1)+"-"+m.group(2)+" "+m.group(3) else: m = re.search("^\s*([0-9]+:[0-9]+)\s*\|\s*(.+?)(\s+\(([0-9]+:[0-9]+)\))?\s*$", line) if m.group(4): start = m.group(1) duration = m.group(4) s = re.search("([0-9]+):([0-9]+)", start) starthour = int(s.group(1)) startmin = int(s.group(2)) s = re.search("([0-9]+):([0-9]+)", duration) min = startmin+int(s.group(2)) hour = starthour+int(s.group(1)) if min >= 60: min -= 60 hour += 1 if hour >= 24: hour -= 24 min = string.zfill(repr(min), 2) hour = string.zfill(repr(hour), 2) outputstr = thatdate+" "+m.group(1)+"-"+hour+":"+min+" "+m.group(2) else: outputstr = thatdate+" "+m.group(1)+" "+m.group(2) print outputstr planner-el/scripts/000077500000000000000000000000001226462314700146115ustar00rootroot00000000000000planner-el/scripts/planner-build.el000066400000000000000000000061121226462314700176670ustar00rootroot00000000000000(add-to-list 'load-path ".") ;; If you want Planner to find all of these programs when ;; byte-compiling Planner, make sure to edit these paths to match your ;; configuration. (add-to-list 'load-path "~/elisp/muse/lisp") (add-to-list 'load-path "~/elisp/remember") (add-to-list 'load-path "~/elisp/bbdb/lisp") (add-to-list 'load-path "~/elisp/erc") (add-to-list 'load-path "~/elisp/gnats") (add-to-list 'load-path "~/elisp/gnus/lisp") (add-to-list 'load-path "~/elisp/psvn") (add-to-list 'load-path "~/elisp/vm") (add-to-list 'load-path "~/elisp/w3m") (add-to-list 'load-path "~/elisp/wl") (add-to-list 'load-path "~/elisp/xtla") (defun planner-elint-files () (require 'elint) (elint-initialize) (defvar nomessage t) (load "planner" nil nomessage) (load "muse-mode" nil nomessage) (dolist (file (directory-files "." nil "\\.el$")) (setq file (substring file 0 (string-match "\\.el$" file))) (load file nil nomessage)) (add-to-list 'elint-standard-variables 'current-prefix-arg) (add-to-list 'elint-standard-variables 'command-line-args-left) (add-to-list 'elint-standard-variables 'buffer-file-coding-system) (add-to-list 'elint-standard-variables 'save-some-buffers-action-alist) (add-to-list 'elint-standard-variables 'emacs-major-version) (add-to-list 'elint-standard-variables 'emacs-minor-version) (add-to-list 'elint-standard-variables 'emacs-version) (add-to-list 'elint-standard-variables 'window-system) (add-to-list 'elint-standard-variables 'debug-on-error) (add-to-list 'elint-standard-variables 'planner-mode-abbrev-table) (dolist (file command-line-args-left) (find-file file) (message "Checking %s ..." file) (elint-current-buffer) (with-current-buffer (elint-get-log-buffer) (goto-char (point-min)) (forward-line 2) (while (not (or (eobp) (looking-at "^Linting complete"))) (message (buffer-substring (planner-line-beginning-position) (planner-line-end-position))) (forward-line 1))) (kill-buffer (current-buffer)))) (defun planner-generate-autoloads () (interactive) (defvar autoload-package-name) (defvar command-line-args-left) (defvar generated-autoload-file) (require 'autoload) (setq generated-autoload-file (expand-file-name "planner-autoloads.el")) (setq command-line-args-left (mapcar #'expand-file-name command-line-args-left)) (if (featurep 'xemacs) (progn (setq autoload-package-name "planner") (batch-update-autoloads)) (find-file generated-autoload-file) (delete-region (point-min) (point-max)) (insert ";;; planner-autoloads.el --- autoloads for Planner ;; ;;; Code: ") (save-buffer 0) (batch-update-autoloads) (find-file generated-autoload-file) (goto-char (point-max)) (insert ?\n) (insert "(provide 'planner-autoloads) ;;; planner-autoloads.el ends here ;; ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t ;; End: ") (insert ?\n) (save-buffer 0) (kill-buffer (current-buffer)))) planner-el/test/000077500000000000000000000000001226462314700141015ustar00rootroot00000000000000planner-el/test/planner-cyclic-test.el000066400000000000000000000021041226462314700203000ustar00rootroot00000000000000;;; Test cases for planner ;;; Sacha Chua (sacha@free.net.ph) ;; Just load this and complain loudly if there are any errors. ;; It only tests a handful of functions right now. (require 'muse) (require 'planner) (require 'planner-cyclic) (require 'planner-test) (planner-test "planner-cyclic-generate-task" '(("2004.03.09" "#A0 _ Study German" "#A0 _ Study German from 2004.03.09") ("2004.03.09" "#A0 _ Study German (GermanStudies)" "#A0 _ Study German from 2004.03.09 (GermanStudies)") ("2004.03.09" "#B0 _ Study German (GermanStudies)" "#B0 _ Study German from 2004.03.09 (GermanStudies)")) (lambda (test-name date task-string expected-output-after-format) (let ((output (planner-format-task (planner-cyclic-generate-task date task-string)))) (unless (string= output expected-output-after-format) (error "%s: output %s expected %s" test-name output expected-output-after-format))))) (provide 'planner-cyclic-test) ;; planner-cyclic-test.el ends here ;;;_* Local emacs vars. ;; Local variables: ;; change-log-default-name: "../ChangeLog" ;; End: planner-el/test/planner-test.el000066400000000000000000000125541226462314700170460ustar00rootroot00000000000000;;; Test cases for planner ;;; Sacha Chua (sacha@free.net.ph) ;; Just load this and complain loudly if there are any errors. ;; It only tests a handful of functions right now. (require 'muse-project) (require 'planner) (defun planner-test (test-name test-cases test-function) (while test-cases (apply test-function test-name (car test-cases)) (setq test-cases (cdr test-cases)))) (planner-test "planner-task-info-from-string" '(("2004.03.01" "#A0 _ Test this function" ("2004.03.01" "A" "0" "_" "Test this function" nil nil nil "2004.03.01")) ("2004.03.01" "#A0 _ Test this function (PlanPage)" ("2004.03.01" "A" "0" "_" "Test this function" "PlanPage" "PlanPage" "PlanPage" "2004.03.01")) ("2004.03.01" "#A0 _ Test this function ([[PlanPage]])" ("2004.03.01" "A" "0" "_" "Test this function" "PlanPage" "[[PlanPage]]" "PlanPage" "2004.03.01")) ("2004.03.01" "#A0 _ Test this function ([[SomePage][Really]])" ("2004.03.01" "A" "0" "_" "Test this function" "SomePage" "[[SomePage][Really]]" "SomePage" "2004.03.01")) ("2004.03.01" "#A0 _ Test this function (NotPlanPage) junk" ("2004.03.01" "A" "0" "_" "Test this function (NotPlanPage) junk" nil nil nil "2004.03.01")) ("2004.03.01" "#A0 _ Test this function (NotPlanPage) (PlanPage)" ("2004.03.01" "A" "0" "_" "Test this function (NotPlanPage)" "PlanPage" "PlanPage" "PlanPage" "2004.03.01")) ("PlanPage" "#A0 _ Test this function" ("PlanPage" "A" "0" "_" "Test this function" nil nil "PlanPage" nil)) ("PlanPage" "#A0 _ Test this function (2004.03.01)" ("PlanPage" "A" "0" "_" "Test this function" "2004.03.01" "2004.03.01" "PlanPage" "2004.03.01")) ("PlanPage" "#A0 _ Test this function (2004.03.01) junk" ("PlanPage" "A" "0" "_" "Test this function (2004.03.01) junk" nil nil "PlanPage" nil)) ("PlanPage" "#A0 _ Test this function (2004.03.02) (2004.03.01)" ("PlanPage" "A" "0" "_" "Test this function (2004.03.02)" "2004.03.01" "2004.03.01" "PlanPage" "2004.03.01")) ("PlanPage" "#B1 X Completed task" ("PlanPage" "B" "1" "X" "Completed task" nil nil "PlanPage" nil)) ("PlanPage" "#B1 X Completed task " ("PlanPage" "B" "1" "X" "Completed task" nil nil "PlanPage" nil)) ("2004.03.01" "#A _ No priority" ("2004.03.01" "A" nil "_" "No priority" nil nil nil "2004.03.01"))) (lambda (test-name page-name string expected-result) (let ((output (planner-task-info-from-string page-name string))) (unless (equal output expected-result) (error "%s: output %s expected %s" test-name output expected-result))))) (planner-test "planner-format-task" '(("2004.03.01" "#A0 _ Test this function" ("2004.03.01" "A" "0" "_" "Test this function" nil nil nil "2004.03.01")) ("2004.03.01" "#A0 _ Test this function (PlanPage)" ("2004.03.01" "A" "0" "_" "Test this function" "PlanPage" "PlanPage" "PlanPage" "2004.03.01")) ("2004.03.01" "#A0 _ Test this function (PlanPage)" ("2004.03.01" "A" "0" "_" "Test this function" "PlanPage" "[[PlanPage]]" "PlanPage" "2004.03.01")) ("2004.03.01" "#A0 _ Test this function ([[SomePage][Really]])" ("2004.03.01" "A" "0" "_" "Test this function" "SomePage" "[[SomePage][Really]]" "SomePage" "2004.03.01")) ("2004.03.01" "#A0 _ Test this function (NotPlanPage) junk" ("2004.03.01" "A" "0" "_" "Test this function (NotPlanPage) junk" nil nil nil "2004.03.01")) ("2004.03.01" "#A0 _ Test this function (NotPlanPage) (PlanPage)" ("2004.03.01" "A" "0" "_" "Test this function (NotPlanPage)" "PlanPage" "PlanPage" "PlanPage" "2004.03.01")) ("PlanPage" "#A0 _ Test this function" ("PlanPage" "A" "0" "_" "Test this function" nil nil "PlanPage" nil)) ("PlanPage" "#A0 _ Test this function (2004.03.01)" ("PlanPage" "A" "0" "_" "Test this function" "2004.03.01" "2004.03.01" "PlanPage" "2004.03.01")) ("PlanPage" "#A0 _ Test this function (2004.03.01) junk" ("PlanPage" "A" "0" "_" "Test this function (2004.03.01) junk" nil nil "PlanPage" nil)) ("PlanPage" "#A0 _ Test this function (2004.03.02) (2004.03.01)" ("PlanPage" "A" "0" "_" "Test this function (2004.03.02)" "2004.03.01" "2004.03.01" "PlanPage" "2004.03.01")) ("PlanPage" "#B1 X Completed task" ("PlanPage" "B" "1" "X" "Completed task" nil nil "PlanPage" nil)) ("2004.03.01" "#A _ No priority" ("2004.03.01" "A" nil "_" "No priority" nil nil nil "2004.03.01"))) (lambda (test-name page-name expected-result info) (with-muse-project planner-project (let ((output (planner-format-task info))) (unless (equal output expected-result) (error "%s: output %s expected %s" test-name output expected-result)))))) (planner-test "planner-install-extra-task-keybindings" nil (lambda (test-case) (with-muse-project planner-project (let ((temp (copy-keymap planner-mode-map))) (planner-install-extra-task-keybindings) (setq planner-mode-map temp))))) (planner-test "planner-strip-whitespace" '(("Hello world" "Helloworld") ("Hello too" "Hellotoo") ("Hello\nthree" "Hellothree")) (lambda (test-name string expected-result) (let ((output (planner-strip-whitespace string))) (unless (equal output expected-result) (error "%s: output %s expected %s" test-name output expected-result))))) (provide 'planner-test) ;;;_* Local emacs vars. ;; Local variables: ;; change-log-default-name: "../ChangeLog" ;; End: ;;; planner-test.el ends here