[O] Idea: insert "current sort order" property
What I'm imagining is a command executed on a headline to insert a property into each of its children "fixing" the current order; something like ":sorted:01", ":sorted:02" etc. Ideally there would be a prompt for the property key (or part of it) so that there could be more than one such property for a particular headline, but with the option to simplify the usage and consistency by having just one property key as a default and no prompt. One of my uses of org-mode is to list songs (Lieder) that I am currently working on, and I mark them up with special todo states and tags relating to my workflow - e.g. findscore, translate, memorise etc. I've also been known to add properties such as 1st line text (if different from title), poet, and pagenumber. While I'm dealing with a list of repertoire (there's a lot of bitty admin involved!) I've found it useful to sort alphabetically, by TODO state and by these properties, but I'd like to be able to retain the order in which the songs will be performed. I know I could manually add such a property to each headline myself but I'd really love to be able to quickly "fix" the order of my sorted headings by automating a ":sorted:" property. Another use I can imagine for this is when juggling an outline, one could "fix" an order that reads well, and then play around with it to see how it might flow better, knowing that it would be easy to return to the last preferred sort-order - like a rollback. During the last few weeks I would have made use of this not only when working on songs, but also when designing song programmes and writing my resumé. If a sorted headline got moved to a new parent its sort-order might be a duplicate one of its siblings, but I don't really see that as a problem - the user knows it's "only text" after all. I don't know whether it might be desired to similarly fix the sort-order of 1st level headlines; perhaps the command could act per current file, with a < to narrow down to the current tree. I'm also not sure how to deal with larger numbers - 01-99 seems like a good default but could one have an option for 001-999? I also wonder about adding the property to more than one level at a time, but might that be a bit much in terms of affecting performance? Does anyone else see this as potentially useful? Gez GNU Emacs 23.3.1 and org-version 7.7
Re: [O] Idea: insert "current sort order" property
Hi, Gez, On 10/7/11 5:02 PM, Gez wrote: What I'm imagining is a command executed on a headline to insert a property into each of its children "fixing" the current order; something like ":sorted:01", ":sorted:02" etc. I think this is a neat idea, and can see some uses for it for my own stuff. I've made a first pass below. Please test it and let me know how it works for you (and please *don't* test it on anything valuable without backing up first!). Ideally there would be a prompt for the property key (or part of it) so that there could be more than one such property for a particular headline, but with the option to simplify the usage and consistency by having just one property key as a default and no prompt. More or less done. There'll be a prompt anyway, but just hit RET to select the default ("OutlineIndex"). If a sorted headline got moved to a new parent its sort-order might be a duplicate one of its siblings, but I don't really see that as a problem - the user knows it's "only text" after all. The below will just do sequential numbering, as you suggested (01, 02, 03...) Then, as long as you've only changed the order of siblings at each level, the order can be restored by sorting on the outline-index property (C-c ^ r) for each parent. Irretrievable chaos may and probably will result if headlines are demoted, promoted, or moved to new parents. As long as the user's fine with that, everything's fine. An obvious refinement would be to do true outline numbering (e.g. 01, 01-01, 01-01-01, 01-01-02, 01-02-01, 01-02-02 ...). Then you could restore the original outline entirely no matter how headings have been moved around. But you couldn't do that by sorting; making that useful would take additional code, so I haven't implemented it (yet). I don't know whether it might be desired to similarly fix the sort-order of 1st level headlines; perhaps the command could act per current file, with a < to narrow down to the current tree. The below will not number the entry at point, because that could break a numbering already set at that level. It will number its direct children. With prefix, it will number all its descendants. See how it works for you. I made it the default behavior to number only the direct children of the entry at point, since littering the whole tree with property drawers is not necessarily what you want to do. I'm also not sure how to deal with larger numbers - 01-99 seems like a good default but could one have an option for 001-999? I also wonder about adding the property to more than one level at a time, but might that be a bit much in terms of affecting performance? Solved; the below counts the total number of headings first, then adjusts the zero padding accordingly. Code follows. Yours, Christian #+begin_src emacs-lisp (defun cm/org-store-outline-order (arg prop) "Store the outline of the subtree of the entry at point by setting the property PROP of each direct child entry to its current position in the tree. With prefix ARG, store the position of the whole subtree. The tree can be restored to the stored outline by sorting on the property with `C-c ^ r'. Note that this will only work properly on the order of each subtree; if headings are demoted, promoted, or moved into different subtrees, the result may or may not be nonsense, but it will be impossible to restore the original order by sorting." (interactive "P\nsProperty key (default OutlineIndex): ") (if (string= prop "") (setq prop "OutlineIndex")) (if (or (not (org-map-entries t (concat prop "={.}") 'tree)) (y-or-n-p "Property exists; overwrite? ")) (let* ((match (format "LEVEL%s%s" (if arg ">=" "=") (1+ (org-current-level (counter 1) (width (1+ (floor (log10 (length (org-map-entries t match 'tree)) (fstr (concat "%0" (number-to-string width) "d"))) (org-map-entries '(progn (org-set-property prop (format fstr counter)) (setq counter (1+ counter))) match 'tree) (message "" #+end_src
Re: [O] Idea: insert "current sort order" property
Thanks, Christian. Please forgive my ignorance but what should I do with the code? I've not done anything more advanced than org-customize before. Gez On 11 October 2011 20:46, Christian Moe wrote: > Hi, Gez, > > > On 10/7/11 5:02 PM, Gez wrote: > >> What I'm imagining is a command executed on a headline to insert a >> property into each of its children "fixing" the current order; >> something like ":sorted:01", ":sorted:02" etc. >> > > I think this is a neat idea, and can see some uses for it for my own stuff. > I've made a first pass below. Please test it and let me know how it works > for you (and please *don't* test it on anything valuable without backing up > first!). > > > > Code follows. Yours, > Christian > > #+begin_src emacs-lisp > (defun cm/org-store-outline-order (arg prop) >"Store the outline of the subtree of the entry at point by > setting the property PROP of each direct child entry to its > current position in the tree. With prefix ARG, store the position > of the whole subtree. The tree can be restored to the stored > outline by sorting on the property with `C-c ^ r'. Note that this > will only work properly on the order of each subtree; if headings > are demoted, promoted, or moved into different subtrees, the > result may or may not be nonsense, but it will be impossible to > restore the original order by sorting." >(interactive "P\nsProperty key (default OutlineIndex): ") >(if (string= prop "") (setq prop "OutlineIndex")) >(if (or (not (org-map-entries t (concat prop "={.}") 'tree)) >(y-or-n-p "Property exists; overwrite? ")) >(let* ((match (format "LEVEL%s%s" > (if arg ">=" "=") > (1+ (org-current-level > (counter 1) > (width (1+ (floor (log10 (length (org-map-entries t match > 'tree)) > (fstr (concat "%0" (number-to-string width) "d"))) > (org-map-entries > '(progn > (org-set-property prop >(format fstr counter)) > (setq counter (1+ counter))) > match 'tree) > (message "" > #+end_src >
Re: [O] Idea: insert "current sort order" property
Hi, You can copy the code into a buffer and `evaluate' it, i.e. teach Emacs the new function for this session. You evaluate an elisp expression by placing point right after the last closing parenthesis and pressing `C-x C-e'. When you do, the minibuffer should display the name of the function. After this, Emacs will only remember the function for the rest of the session. If you like it and want it available the next time you start Emacs, just copy it into your .emacs file (only the bit *between* the #+BEGIN_SRC and #+END_SRC lines). This is the basic drill for using little snippets of code that don't merit a file of their own. Since this is an interactive function, you can call it with `M-x'. Place point in the appropriate parent entry in your music outline and try `M-x cm/org-store-outline-order'. Options: - Since the code in this case is surrounded by a #+BEGIN_SRC block, if you copy it into an Org buffer, you can also evaluate it simply by `C-c C-c' with point anywhere on the code block. - You can change the name and drop the `cm/' prefix if you like (I just use it as a reminder this is my hack, not part of Org-mode). Yours, Christian On 10/12/11 1:35 PM, Gez wrote: Thanks, Christian. Please forgive my ignorance but what should I do with the code? I've not done anything more advanced than org-customize before. Gez On 11 October 2011 20:46, Christian Moe mailto:m...@christianmoe.com>> wrote: Hi, Gez, On 10/7/11 5:02 PM, Gez wrote: What I'm imagining is a command executed on a headline to insert a property into each of its children "fixing" the current order; something like ":sorted:01", ":sorted:02" etc. I think this is a neat idea, and can see some uses for it for my own stuff. I've made a first pass below. Please test it and let me know how it works for you (and please *don't* test it on anything valuable without backing up first!). Code follows. Yours, Christian #+begin_src emacs-lisp (defun cm/org-store-outline-order (arg prop) "Store the outline of the subtree of the entry at point by setting the property PROP of each direct child entry to its current position in the tree. With prefix ARG, store the position of the whole subtree. The tree can be restored to the stored outline by sorting on the property with `C-c ^ r'. Note that this will only work properly on the order of each subtree; if headings are demoted, promoted, or moved into different subtrees, the result may or may not be nonsense, but it will be impossible to restore the original order by sorting." (interactive "P\nsProperty key (default OutlineIndex): ") (if (string= prop "") (setq prop "OutlineIndex")) (if (or (not (org-map-entries t (concat prop "={.}") 'tree)) (y-or-n-p "Property exists; overwrite? ")) (let* ((match (format "LEVEL%s%s" (if arg ">=" "=") (1+ (org-current-level (counter 1) (width (1+ (floor (log10 (length (org-map-entries t match 'tree)) (fstr (concat "%0" (number-to-string width) "d"))) (org-map-entries '(progn (org-set-property prop (format fstr counter)) (setq counter (1+ counter))) match 'tree) (message "" #+end_src
Re: [O] Idea: insert "current sort order" property
On 12 October 2011 13:16, Christian Moe wrote: If you like it and want it available the next time you start Emacs, > just copy it into your .emacs file (only the bit *between* the #+BEGIN_SRC > and #+END_SRC lines). It's in my .emacs now - I have just tested it and it seems to work perfectly. Thank you so much for it. And thanks for explaining what to do with code snippets. I do use revisioning, but Is there a protocol I should use for testing code snippets before using them on my original data or can they be considered safe after being run once? One thing that might be useful to add to the code please ... If when prompting for the property key, TAB brought up the list of auto-complete keys (like when using C-c C-x p) that would make for easier maintenance and consistency; e.g. when I deliberately want to overwrite a previous outline index it would avoid a second set of properties being written accidentally if I made a typo. Gez > On 10/12/11 1:35 PM, Gez wrote: >> >> Thanks, Christian. Please forgive my ignorance but what should I do >> with the code? I've not done anything more advanced than >> org-customize before. >> >> Gez >
Re: [O] Idea: insert "current sort order" property
On 10/12/11 5:59 PM, Gez wrote: I do use revisioning, but Is there a protocol I should use for testing code snippets before using them on my original data or can they be considered safe after being run once? Save often; backup/commit often; be ready to hit 'undo'...? Do the first test run on mock data in a test.org file? One thing that might be useful to add to the code please ... If when prompting for the property key, TAB brought up the list of auto-complete keys (like when using C-c C-x p) that would make for easier maintenance and consistency; e.g. when I deliberately want to overwrite a previous outline index it would avoid a second set of properties being written accidentally if I made a typo. Then we need a way to keep track of what property keys are used to store outlines in, so we can offer those and only those for completion. (We don't want to offer all the property keys used in the buffer -- that's an invitation to overwrite data.) So in my second pass (below), when you use a :foo: property to store the outline index, `foo' gets added to a list of keys in the :Stored_outlines: property of the parent. When you store an outline, the prompt for a property key offers completion on all the keys stored in :Stored_outlines:. See how this works for you. Yours, Christian #+BEGIN_SRC emacs-lisp (defun cm/org-store-outline-order (arg prop) "Store the heading order of the subtree of the entry at point by setting the property PROP of each direct child entry to its current position in the tree. With prefix ARG, store the position of the whole subtree. You can store different heading orders in the same subtree by using different keys as PROP; these will be listed in the Stored_Outlines property of the parent entry. The tree can be restored to a given stored outline by sorting on the appropriate property with `C-c ^ r'. Note that this will only work properly on the order of each subtree; if headings are demoted, promoted, or moved into different subtrees, the result may or may not be nonsense, but it will be impossible to restore the original order by sorting." (interactive "P\ni") (let* ((match (format "LEVEL%s%s" (if arg ">=" "=") (1+ (org-current-level (counter 1) (width (1+ (floor (log10 (length (org-map-entries t match 'tree)) (fstr (concat "%0" (number-to-string width) "d")) (defaultprop "OutlineIndex") (keychain "Stored_Outlines") (keys (org-entry-get-multivalued-property (point) keychain))) (unless prop (setq prop (org-icompleting-read (concat "Property to use [" defaultprop "]: ") (mapcar 'list keys) nil nil nil nil defaultprop))) (when (or (not (org-map-entries t (concat prop "={.}") 'tree)) (y-or-n-p "Property exists; overwrite? ")) (org-entry-add-to-multivalued-property (point) "Stored_Outlines" prop) (org-map-entries '(progn (org-set-property prop (format fstr counter)) (setq counter (1+ counter))) match 'tree) (message "" #+END_SRC Gez On 10/12/11 1:35 PM, Gez wrote: Thanks, Christian. Please forgive my ignorance but what should I do with the code? I've not done anything more advanced than org-customize before. Gez
Re: [O] Idea: insert "current sort order" property
On 12 October 2011 20:51, Christian Moe wrote: > > Then we need a way to keep track of what property keys are used to store > outlines in, so we can offer those and only those for completion. (We don't > want to offer all the property keys used in the buffer -- that's an > invitation to overwrite data.) That makes sense > > So in my second pass (below), when you use a :foo: property to store the > outline index, `foo' gets added to a list of keys in the :Stored_outlines: > property of the parent. When you store an outline, the prompt for a property > key offers completion on all the keys stored in :Stored_outlines:. See how > this works for you. > Thanks. I got it to work from a scratch buffer but not from .emacs (previous version worked fine from my .emacs). Restarting emacs showed an error. --- Warning (initialization): An error occurred while loading `q:/Q_Synced/Portable/emacs-23.3/home/.emacs': Invalid read syntax: # To ensure normal operation, you should investigate and remove the cause of the error in your initialization file. Start Emacs with the `--debug-init' option to view a complete error backtrace. - I couldn't copy the whole backtrace here (an encoding issue?) Here's the start and end of it in case it's any help: ___ Debugger entered--Lisp error: (invalid-read-syntax "#") eval-buffer(# nil "q:/Q_Synced/Portable/emacs-23.3/home/.emacs" nil t) ; Reading at buffer position 13136 load-with-code-conversion("q:/Q_Synced/Portable/emacs-23.3/home/.emacs" "q:/Q_Synced/Portable/emacs-23.3/home/.emacs" t t) load("~/.emacs" t t) #[nil [init-file-user system-type user-init-file-1 user-init-file otherfile source ms-dos "~" "/_emacs" windows-nt directory-files nil "^\\.emacs\\(\\.elc?\\)?$" "~/.emacs" "^_emacs\\(\\.elc?\\)?$" "~/_emacs" "/.emacs" t load expand-file-name "init" file-name-as-directory "/.emacs.d" file-name-extension "elc" file-name-sans-extension ".el" file-exists-p file-newer-than-file-p message "Warning: %s is newer than %s" sit-for 1 "default" alt inhibit-default-init inhibit-startup-screen] 7]() command-line() normal-top-level() _ Gez
Re: [O] Idea: insert "current sort order" property
Hi, Not sure I can help; I don't quite see how this error could be caused by anything in the code I sent you. Is this happening on the same system as you used before? What version of Emacs are you on when this happens? Yours, Christian On 10/13/11 1:40 PM, Gez wrote: Thanks. I got it to work from a scratch buffer but not from .emacs (previous version worked fine from my .emacs). Restarting emacs showed an error. --- Warning (initialization): An error occurred while loading `q:/Q_Synced/Portable/emacs-23.3/home/.emacs': Invalid read syntax: # To ensure normal operation, you should investigate and remove the cause of the error in your initialization file. Start Emacs with the `--debug-init' option to view a complete error backtrace. - I couldn't copy the whole backtrace here (an encoding issue?) Here's the start and end of it in case it's any help: ___ Debugger entered--Lisp error: (invalid-read-syntax "#") eval-buffer(# nil "q:/Q_Synced/Portable/emacs-23.3/home/.emacs" nil t) ; Reading at buffer position 13136 load-with-code-conversion("q:/Q_Synced/Portable/emacs-23.3/home/.emacs" "q:/Q_Synced/Portable/emacs-23.3/home/.emacs" t t) load("~/.emacs" t t) #[nil [init-file-user system-type user-init-file-1 user-init-file otherfile source ms-dos "~" "/_emacs" windows-nt directory-files nil "^\\.emacs\\(\\.elc?\\)?$" "~/.emacs" "^_emacs\\(\\.elc?\\)?$" "~/_emacs" "/.emacs" t load expand-file-name "init" file-name-as-directory "/.emacs.d" file-name-extension "elc" file-name-sans-extension ".el" file-exists-p file-newer-than-file-p message "Warning: %s is newer than %s" sit-for 1 "default" alt inhibit-default-init inhibit-startup-screen] 7]() command-line() normal-top-level() _ Gez
Re: [O] Idea: insert "current sort order" property
That was my duh - I accidentally left a # in when copying to my .emacs. It works fine now. Thank you. Gez On 13 October 2011 13:39, Christian Moe wrote: > Hi, > > Not sure I can help; I don't quite see how this error could be caused by > anything in the code I sent you. Is this happening on the same system as you > used before? What version of Emacs are you on when this happens? > > Yours, > Christian > > On 10/13/11 1:40 PM, Gez wrote: > >> Thanks. I got it to work from a scratch buffer but not from .emacs >> (previous version worked fine from my .emacs). Restarting emacs >> showed an error. >> >> --- >> Warning (initialization): An error occurred while loading >> `q:/Q_Synced/Portable/emacs-23.3/home/.emacs': >> >> Invalid read syntax: # >> >> To ensure normal operation, you should investigate and remove the >> cause of the error in your initialization file. Start Emacs with >> the `--debug-init' option to view a complete error backtrace. >> - > >