Topic: [workaround] obpipemenu-places : perl + utf-8 problem ?

Hello

I use obpipemenu-places to display filenames in openbox but I have some files with very long names so the display is like this :

start of the name ... end of the name.avi

I modified the script to display only the 30 first characters so the output is now :

start of the name 

The modified function in the script :

sub mk_file_element {
    my ($path, $name) = @_;
    my $label = $name;
    # escape ampersand in pathnames
    $path =~ s/&/&/g;
    $name =~ s/&/&/g;
    my $short_name = substr($name, 0,  30);
    $short_name =~ s/_/__/g;
    # return "$short_name\n";
    return "<item label=\"$short_name\">".
           "\n\t<action name=\"Execute\">".
           "\n\t\t<execute>$cmd '$path/$name'</execute>".
           "\n\t</action>"
           . "\n</item>\n";
     
}

But my problem is with filenames with accents, the output can be broken when last character is special (éùèç):

$ ./obpipemenu-places /films |   grep enfer
<item label="Raoul Walsh-1949-L'enfer est �">
        <execute>thunar '/films/Raoul Walsh-1949-L'enfer est à lui.avi'</execute>

As you see, the à became a .

So any idea for solving this problem , pleeeeeease ? Thanks smile

Last edited by wlourf (2011-03-25 22:51:07)

Re: [workaround] obpipemenu-places : perl + utf-8 problem ?

I have that as well in most Office suites, except the one from a standard Ubuntu install. I'm not trying to hijack your topic, but this might be related? I would like to know what the problem could be, as I find this highly annoying.

Let's do it and don't screw it.
      Github || Deviantart

Re: [workaround] obpipemenu-places : perl + utf-8 problem ?

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 smile

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,'_','__'),'&','&amp;')
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,'&','&amp;') .. "' " .. 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,'&','&amp;') .. "\""
            .."</execute></action>"
        .. "\n</item>"    )
end

print("</openbox_pipe_menu>")

Last edited by wlourf (2011-03-26 10:11:02)