You are not logged in.
Sometimes you want to re-open a file you've just been working on and it would be handy not to have to dive into a "places" menu to dig it out. There's a file in your user directory called .recently-used.xbel which is updated by gtk apps in particular and holds the file paths and what application was used to open them, along with other data like mime-types. It's a bit odd sometimes ( doesn't always update right away ), and not all apps use it, but seems reasonably usable. This script was inspired by http://openbox.org/wiki/Openbox:Pipemen … tfilesxbel but changed quite a bit while I was playing with it. Stuff being done by grep, read and sed seemed all doable by awk, so calling up one utility instead of three, and giving me an excuse to get down and learn some awk... The end result is quite fast I think, and instead of using something like xdg-open to open files it gets the previously used application. Another small improvement is that unusual characters ( even quotes and backslashes, and multi-byte characters like Japanese ) in filenames are displayed correctly, and don't break the "open" command, so you can have files called \_<"">_ if you want...
To use, copy the code into a file called (e.g.) recently_opened_menu.sh, make it executable, then add this:
<menu id="recent" label="Recent Files" execute="/path/to/recently_opened_menu.sh" />to your ~/.config/openbox/menu.xml file.
Anyway, check it out if you're interested, and please let me know if you find any problems:
#!/bin/sh
# recently_opened_menu.sh - a script to parse .recently-used.xbel
# and generate openbox pipe menu
# Copyright (C) 2010 John Crawley
#
# 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.
# version 2012/07/01
# Usage: add
# <menu id="recent" label="Recent Files" execute="/path/to/recently_opened_menu.sh" />
# to your .config/openbox/menu.xml, or use with dash_places_menu.sh (see comments there)
maximum_entries=15 # max. number of entries in menu
#######################################################################
# look for recently-used.xbel
if [ $XDG_DATA_HOME ] && [ -r "${XDG_DATA_HOME}/recently-used.xbel" ]
then
file_path="${XDG_DATA_HOME}/recently-used.xbel"
elif [ -r "${HOME}/.local/share/recently-used.xbel" ]
then
file_path="${HOME}/.local/share/recently-used.xbel"
elif [ -r "${HOME}/.recently-used.xbel" ]
then
file_path="${HOME}/.recently-used.xbel"
else
echo "$0: cannot find a readable recently-used.xbel file" >&2
echo '<openbox_pipe_menu>
<separator label="No recently-used.xbel file found." />
</openbox_pipe_menu>'
exit 1
fi
# if argument is --clear, empty .recently-used.xbel
[ "$1" = '--clear' ] && {
cat <<':EOF' > "${file_path}"
<?xml version="1.0" encoding="UTF-8"?>
<xbel version="1.0"
xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"
xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"
>
</xbel>
:EOF
exit
}
maximum_entries=$((maximum_entries+2))
pre=' <item label="'
mid='">
<action name="Execute"><command>'
post='</command></action>
</item>'
files=$( tac "${file_path}" | awk -v MAX="$maximum_entries" -v PR="$pre" -v MI="$mid" -v PO="$post" 'BEGIN {
RS="</bookmark>";
FS="<info>";
}
(NR == MAX) {exit}
!/<bookmark/ {next}
!/href=[\"'\'']file:\/\// {next}
# $1 is the command, $2 the file path
{
sub(/^.*exec=\"\&apos\;/,"",$1)
sub(/\&apos\;.*$/,"",$1)
sub(/ *%./,"",$1)
sub(/^.*file:\/\//,"",$2)
sub(/[\"'\''].*$/,"",$2)
gsub(/%22/,"\\"",$2)
gsub(/%3C/,"\\<",$2)
gsub(/%3E/,"\\>",$2)
name=$2
sub(/^.*\//,"",name)
gsub(/_/,"__",name)
gsub(/\'/,"\\'\\"\\'\\"\\'",$2)
print (PR name MI $1 " '"'"'" $2 "'"'"'" PO)
}' )
# use perl to decode urlencoded characters
files=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0]);' "$files")
output='<openbox_pipe_menu>
'"$files"'
<separator />
<item label="Clear Recent Files">
<action name="Execute">
<command>
''"$0"'' --clear
</command>
</action>
</item>
</openbox_pipe_menu>
'
printf '%s' "$output" # printf because echo sometimes eats backslashesThe bit of perl voodoo came from here originally, but don't ask me to explain how it works. It does anyway, and doesn't seem too slow. If any perl or awk gurus can suggest improvements to any of this, grateful as always. 
edit: Now overwrites .recently-used.xbel to clear the file list, instead of just deleting it.
edit 110209 Bugfix: entries without a reference to a local file (path starting 'file://') would break the menu. Now they're ignored. This menu is for files on your local system only.
edit 110210 Now copes with both single and double quotes for xml tag attributes in .recently-used.xbel. ( Probably unnecessary
)
edit 110520 Amended to check possible locations of recently-used.xbel and use the first one found. (The file moves to ~/.local.share if libgtk2.0-0 is upgraded from 2.20 to 2.24.)
edit 110602 Escaping modified to work with gawk as well as mawk. (Ampersands in replacement strings preceded by two backslashes instead of one.)
edit 120704 Underbars (_) in filenames now escaped as __ so Openbox displays them correctly. Also, if recently-used.xbel was missing (eg deleted by bleachbit) no menu was output and openbox gave an error message. That has now been replaced by an error message in a tiny menu.
Last edited by johnraff (2012-07-04 05:55:54)
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
I must have eaten something funny today but I am completely at loss when it comes to figuring out how to use this. I can run it in a a terminal and the output is xml code. It seems the script does its thing but how do I get something useful out of it?
TIA
/Martin
Offline
Nice, it would be pretty cool being merged with the places pipe menu, the functionality seems complementary and you'd only need to extract and clean up the url which would make parsing easier.
I have to say despite being a fan of awk, even i would say go with something else for parsing xml/html. Some king of xml awk (Xawk, Hawk ?) for extracting stuff from between tags would be cool, as im sure you've discovered, awks fine for key value pairs or csv, for markup its kind of rubbish.
ps just been doing some work on the places menu posting it on the relevant thread now.
Last edited by benj1 (2010-11-17 19:56:19)
- - - - - - - - Wiki Pages - - - - - - -
#! install guide *autostart programs, modify the menu & keybindings
configuring Conky *installing scripts
Offline
I must have eaten something funny today but I am completely at loss when it comes to figuring out how to use this. I can run it in a a terminal and the output is xml code. It seems the script does its thing but how do I get something useful out of it?
TIA
/Martin
Its a pipemenu for Openbox WM.
Using obmenu you can add a pipemenu and then you have to have this script as the command.
Note: ** Please read before posting **
BTW if you wish to contact me, send me an e-mail instead of a PM.
Online
I must have eaten something funny today but I am completely at loss when it comes to figuring out how to use this. I can run it in a a terminal and the output is xml code. It seems the script does its thing but how do I get something useful out of it?
TIA
/Martin
Sorry I forgot to put that in the first post (I'll add it now). Anyway, either use obmenu as anonymous says, or add this line to your openbox menu.xml at the point where you want it to appear:
<menu execute="/home/username/path/to/filename.sh" id="recent" label="Recent files" />(Change content as necessary.) The menu will appear after you reconfigure openbox, or log out and in again.
Last edited by johnraff (2010-11-19 16:04:39)
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
it would be pretty cool being merged with the places pipe menu, the functionality seems complementary and you'd only need to extract and clean up the url which would make parsing easier.
Yes I thought about that, maybe adding it as a sub-menu at the top of "places". The only snag there would be that it would appear at the top of every subdirectory's menu - might get irritating. Maybe add a test so that it only appears if the places menu is looking at ~/. Alternatively, actually combine the code so that, say, half a dozen recent files appear at the top of the places menu, again only if the directory is ~/.
I have to say despite being a fan of awk, even i would say go with something else for parsing xml/html. Some king of xml awk (Xawk, Hawk ?) for extracting stuff from between tags would be cool, as im sure you've discovered, awks fine for key value pairs or csv, for markup its kind of rubbish.
Well, agreed, sort of. But do those xml awk things come with standard #!? In this case I'm using "</bookmark>" as the line separator (after inverting it with 'tac'), so each "line" corresponds to a file entry, and "<info>" as the field separator so the application should come on one side of that, and the file path on the other. I'm hoping this should be fairly robust, even with all the xml on one line (I must try that out
) or extra tags added or removed... ( As I said, hoping
) I'm quite happy with the speed awk (actually mawk by default for Jaunty or Squeeze) gave here too. It ran through a lot of substitutions much quicker than it would have been calling up sed over and over. 
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
Note to self: I must try this when I get home from work.
Offline
Yes I thought about that, maybe adding it as a sub-menu at the top of "places". The only snag there would be that it would appear at the top of every subdirectory's menu - might get irritating. Maybe add a test so that it only appears if the places menu is looking at ~/. Alternatively, actually combine the code so that, say, half a dozen recent files appear at the top of the places menu, again only if the directory is ~/.
the easiest way could be to just call places.sh within menu.xml as 'places.sh --recent ~/' then parse the --recent to display the recently used menu, the logics already in place for the --open flag, you just need two versions of the header that currently contains 'browse here'.
- - - - - - - - Wiki Pages - - - - - - -
#! install guide *autostart programs, modify the menu & keybindings
configuring Conky *installing scripts
Offline
johnraff wrote:Yes I thought about that, maybe adding it as a sub-menu at the top of "places". The only snag there would be that it would appear at the top of every subdirectory's menu - might get irritating. Maybe add a test so that it only appears if the places menu is looking at ~/. Alternatively, actually combine the code so that, say, half a dozen recent files appear at the top of the places menu, again only if the directory is ~/.
the easiest way could be to just call places.sh within menu.xml as 'places.sh --recent ~/' then parse the --recent to display the recently used menu, the logics already in place for the --open flag, you just need two versions of the header that currently contains 'browse here'.
Ah yes, that's a neat idea! 
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
Sorry I forgot to put that in the first post (I'll add it now). Anyway, either use obmenu as anonymous says, or add this line to your openbox menu.xml at the point where you want it to appear:
<menu execute="/home/username/path/to/filename.sh" id="recent" label="Recent files"/>(Change content as necessary.) The menu will appear after you reconfigure openbox, or log out and in again.
Thanks John (and anonymous). Late yesterday evening my brain suddenly got first gear working and after some experimenting it came up with the solution you describe here. I had to remove the trailing / to make it work. By then it was too late to write about my findings, I thought.
/Martin
Offline
johnraff wrote:Sorry I forgot to put that in the first post (I'll add it now). Anyway, either use obmenu as anonymous says, or add this line to your openbox menu.xml at the point where you want it to appear:
<menu execute="/home/username/path/to/filename.sh" id="recent" label="Recent files"/>(Change content as necessary.) The menu will appear after you reconfigure openbox, or log out and in again.
Thanks John (and anonymous). Late yesterday evening my brain suddenly got first gear working and after some experimenting it came up with the solution you describe here. I had to remove the trailing / to make it work. By then it was too late to write about my findings, I thought.
/Martin
Hi Martin, glad it worked, but... what was this trailing slash you had to remove?
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
Note to self: I must try this when I get home from work.
seconded.
must try this when i get back in openbox. ^_^
in honour of Aaron H. Swartz,
make liberating JSTOR (and similar)'s database(s) of knowledge from behind paywalls your #1 priority,
and keep making the world a better place.
live up to what he lived for.
Offline
Thirded (is that even a word?)
when i get back from the forums:P
... and a kind word. -Duke
Offline
Note to self: I must try this when I get home from work.
Tried it, love it. Great work, johnraff 
So, is this pipe menu something that should be included in CrunchBang's default set-up?
Offline
corenominal wrote:Note to self: I must try this when I get home from work.
Tried it, love it. Great work, johnraff
So, is this pipe menu something that should be included in CrunchBang's default set-up?
It's a must-have IMHO.
But maybe with an option to clear the list from the same menu if it's possible...
Another script that replaces the ~/.recently-used.xbel with a blank vanilla one stored somewhere?
Last edited by boromeus (2010-11-19 23:58:55)
Offline
@boromeus There should be a "Clear Recent Files" item at the bottom of the menu. It just deletes the file - it soon gets replaced by something somewhere in the system. But as you say, replacing, or overwriting, it with a "vanilla" version could be a better option?
@corenominal Thanks!
What goes into the default #! is of course your call, based on your criterions, but could I humbly mention the somewhat improved "places" menu? Benj1 has suggested building the "recent files" menu in as a submenu of that; it looks quite easy, and a version that does that will probably appear in a day or three...
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
@corenominal Thanks!
What goes into the default #! is of course your call, based on your criterions, but could I humbly mention the somewhat improved "places" menu? Benj1 has suggested building the "recent files" menu in as a submenu of that; it looks quite easy, and a version that does that will probably appear in a day or three...
I have seen your improved "places menu" thread, but I have yet to try. I will look forward to trying a combined menu. Again, great work! 
Offline
@boromeus There should be a "Clear Recent Files" item at the bottom of the menu. It just deletes the file - it soon gets replaced by something somewhere in the system. But as you say, replacing, or overwriting, it with a "vanilla" version could be a better option?
@corenominal Thanks!
What goes into the default #! is of course your call, based on your criterions, but could I humbly mention the somewhat improved "places" menu? Benj1 has suggested building the "recent files" menu in as a submenu of that; it looks quite easy, and a version that does that will probably appear in a day or three...
I have my own recent files script. Your's is more comprehensive, though, and I'll probably switch to using that. Mine just uses "xdg-open" for opening files. I like your method better.
For clearing the list I have this in the menu:
<item label="Clear Recent Documents">
<action name="Execute"><command>cp $HOME/bin/blank.xbel $HOME/.recently-used.xbel</command></action>
</item>Then the content of the"blank.xbel" file is this:
<?xml version="1.0" encoding="UTF-8"?>
<xbel version="1.0"
xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"
xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"
>
</xbel>Last edited by mobilediesel (2010-11-20 08:26:05)
Offline
oooo weee... I hope this is in 10 >-</
... and a kind word. -Duke
Offline
For clearing the list I have this in the menu:
<item label="Clear Recent Documents"> <action name="Execute"><command>cp $HOME/bin/blank.xbel $HOME/.recently-used.xbel</command></action> </item>Then the content of the"blank.xbel" file is this:
<?xml version="1.0" encoding="UTF-8"?> <xbel version="1.0" xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks" xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info" > </xbel>
I think I might give that a try instead of just deleting the file as at present. Maybe, though, keep that bit of code in the script and use it to overwrite the .recently-used.xbel file - saves having to make another blank.xbel file.
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
Maybe, though, keep that bit of code in the script and use it to overwrite the .recently-used.xbel file - saves having to make another blank.xbel file.
I should add a thumbs-up smiley to these forums.
Offline
Hi Martin, glad it worked, but... what was this trailing slash you had to remove?
Here come a few lines from my menu.xml
<separator/>
<menu execute="resent ~" id="resent" label="Resent files">
</menu>
<menu execute="obpipemenu-places ~" id="places" label="Places"/>
<separator/>I created the Resent files line by copying and changing the Places line. At first it ended with
/>but then I got an error message and the menu was truncated after this point. Removing the / solved the problem. I have no clue to what is going on here. This is pure trial-and-horror 'engineering'. No insight is involved whatsoever.
Looking at the code now I start to wonder if the lone
</menu>line is something I have done by mistake or if it has been there all the time.
/Martin
Offline
Martin, I'm inclined to think you don't need the </menu> at that point. On the other hand, XML tags are supposed to be closed with a final slash, either <tag> ...stuff... </tag> or for tags without a closing tag <tag "attribute" ... />. So really you should have had that final closing slash, just like the line you copied from. Maybe try putting it back and removing the </menu>?
btw the recent files script doesn't need that "~" at the end of its command line. The "places" menu needs it to tell it what folder to start from.
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
The places menu now has an option to add this recent files menu as a submenu at the top. Thanks to Benj1 for the idea 
John
--------------------
( a boring Japan blog , and idle twitterings )
Offline
I think I might give that a try instead of just deleting the file as at present. Maybe, though, keep that bit of code in the script and use it to overwrite the .recently-used.xbel file - saves having to make another blank.xbel file.
I don't know why I didn't think of that. I've done it that way in scripts before, something like:
cat <<':EOF' > $HOME/.recently-used.xbel
<?xml version="1.0" encoding="UTF-8"?>
<xbel version="1.0"
xmlns:bookmark="http://www.freedesktop.org/standards/desktop-bookmarks"
xmlns:mime="http://www.freedesktop.org/standards/shared-mime-info"
>
</xbel>
:EOFmaybe?
Last edited by mobilediesel (2010-11-20 18:23:32)
Offline
Copyright © 2012 CrunchBang Linux.
Proudly powered by Debian. Hosted by Linode.
Debian is a registered trademark of Software in the Public Interest, Inc.