Well, the problem appears when the last character is encoded on 2 bytes (I can be wrong, I'm not sure !!). So the trick is to check the last character. As I don't know how to do it with Perl, I've done it with Lua and it works fine for my needs !
I post the script here if it can be useful to someone 
So the script does the same thing as the obpipemenu-places script in crunchbang, plus :
- it can cut the filename after x characters
- a filter on one or more words can be applied on the pipemenu
Please move the topic to the Tips & tricks section if you, nice moderator, find the script useful !
#!/usr/bin/lua
--[[ pipe-places.lua by wlourf 25 March 2011.
inspired from perl script obpipemenu-places by dircha & all
needs :
sudo apt-get install lua50
# Recursively browse filesystem through openbox3 pipe menus
Usage: add
<menu id="browse" label="Browse" execute="/path/pipe-places.lua path cut filter" />
to your .config/openbox/menu.xml
Arguments are
path is mandatory : path to browse
cut (optional) : cut the filename at the first x characters
filter (optional) : one or more words to filter in path names to display
examples :
browse $HOME without .mp3 or .avi filenames
<menu id="browse" label="Browse" execute="/path/pipe-places.lua ~ .mp3 .avi" />
browse ~/documents and cut filenames at 30 characters
<menu id="browse" label="Browse" execute="/path/pipe-places.lua ~/documents 30" />
browse ~/documents and cut filenames at 30 characters and filter on apple and bananas
<menu id="browse" label="Browse" execute="/path/pipe-places.lua ~/documents 30 apple bananas" />
--doesn't work with apos ' in folder names
]]
local file_manager = 'thunar'
local cmd = 'thunar'
--- END OF PARAMETERS ---
--check parameters
if arg [1] == nil then
print ("This script requires the path to browse as first argument, abort.")
return
end
--if second argument is a number it is used to cut the filename
--remaining arguments are used as filters
local cut=0
local filter={}
local filters=""
local start_filter =2
if tonumber(arg [2]) ~= nil then
cut = arg[2]
start_filter = 3
end
for x=start_filter,table.getn(arg) do
table.insert(filter,arg[x])
filters = filters .. arg[x] .. " "
end
function set_label(s,c)
--set the label displayed in the ob-menu
if c ~= 0 then
lab = string.sub(s,1,c)
else
lab = s
end
if string.byte(lab, string.len(lab)) == 195 then
lab = string.sub(s,1,c-1)
end
return string.gsub(string.gsub(lab,'_','__'),'&','&')
end
local path = arg [1]
local f = io.popen("ls -1p " .. "\"" .. path .. "\"" )
arrayFiles={}
arrayDir={}
while true do
local line = f:read("*l")
local add = true
if line == nil then break end
for x in filter do
if string.find(string.lower(line), string.lower(filter[x])) ~= nil then
add = false
break
end
end
if add then
if string.sub(line,-1) == "/" then
table.insert(arrayDir,line)
else
table.insert(arrayFiles,line)
end
end
end
f:close()
print ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
.. "\n<openbox_pipe_menu>"
.. "\n<item label=\"Browse here...\">"
.. "\n\t<action name=\"Execute\">"
.. "\n\t\t<execute>" .. file_manager .. " " .. path .. "</execute>"
.. "\n\t</action>"
.. "\n</item>\n"
.. "\n<separator />")
for i,k in ipairs(arrayDir) do
lab = set_label(k,cut)
print("<menu id=\"" .. path .. "/" .. k .. "\" label=\"".. string.sub(lab,1,-2)
.. "\" execute=\"" .. arg[0] .. " '" .. path .. "/" .. string.gsub(k,'&','&') .. "' " .. cut .." " .. filters .. " \" />" )
end
for i,k in ipairs(arrayFiles) do
lab = set_label(k,cut)
print("<item label=\"" .. lab .. "\">"
.. "\n\t<action name=\"Execute\"><execute>".. cmd .. " " .. "\"" .. path .. "/".. string.gsub(k,'&','&') .. "\""
.."</execute></action>"
.. "\n</item>" )
end
print("</openbox_pipe_menu>")
Last edited by wlourf (2011-03-26 10:11:02)