Naughty

From awesome
Jump to: navigation, search

Naughty is a lua library that implements popup notifications for awesome3 (git). It's included in current awesome git master. Development branch can be found at naughty branch of awesome git mirror.


Setting up Naughty[edit]

First, you have to include the library in your rc.lua:

require('naughty')

For gentoo users, you must add dbus use for awesome:

sudo flaggie awesome +dbus

If you wish to change default settings, you can redefine any of the following fields. For details refer to luadoc.

naughty.config.defaults.timeout          = 5
naughty.config.defaults.screen           = 1
naughty.config.defaults.position         = "top_right"
naughty.config.defaults.margin           = 4
naughty.config.defaults.height           = 16
naughty.config.defaults.width            = 300
naughty.config.defaults.gap              = 1
naughty.config.defaults.ontop            = true
naughty.config.defaults.font             = beautiful.font or "Verdana 8"
naughty.config.defaults.icon             = nil
naughty.config.defaults.icon_size        = 16
naughty.config.defaults.fg               = beautiful.fg_focus or '#ffffff'
naughty.config.defaults.bg               = beautiful.bg_focus or '#535d6c'
naughty.config.presetss.border_color     = beautiful.border_focus or '#535d6c'
naughty.config.defaults.border_width     = 1
naughty.config.defaults.hover_timeout    = nil

NOTE: in older versions of awesome `naughty.config.default_preset` appears to have been used (the example above works for 3.5.2).

Using Naughty[edit]

To create a notification popup call naughty.notify({args}). Typically you should use

naughty.notify({ text="notification content", icon="/path/to/icon" })


Note that arguments to naughty.notify() are optional. The above example will use pre-configured settings resulting in uniform looking popups with custom text and icon. If you wish to set things on a per-popup basis you can override the defaults by passing required settings with arguments:

naughty.notify({
    text = "notification",
    title = "title",
    position = "top_left"|"top_right"|"bottom_left"|"bottom_right",
    timeout = 5,
    icon="/path/to/image",
    fg="#ffggcc",
    bg="#bbggcc",
    screen = 1,
    ontop = false, 
    run = function () awful.util.spawn("wicd-client") end
})

Also note that you can use some html tags with naughty and thus any spare < will not display.

Feeding Naughty[edit]

Merely loading Naughty into your config will not produce any popups - the main problem is feeding it data.

  • To test the module you can call naughty.notify from Lua prompt.
  • You can call the function from any part of rc.lua (good for extra info from widgets?)
  • To call the function from anything that can execute commands, use awesome-client:
echo 'naughty.notify({title = "testing", text = "naughty", timeout = 10})' | awesome-client -

The last method is good for feeding data from acpid/ivman/etc.

Examples[edit]

Ivman[edit]

Taken from ~/.ivman/IvmConfigActions.xml:

<ivm:Match name="hal.info.linux.driver" value="usb">
 <ivm:Option name="exec" value="echo naughty.notify\({timeout=15, title=\'USB device\',\
      text=\'$hal.info.product$\'}\) | awesome-client -" />
</ivm:Match>

<ivm:Match name="hal.volume.is_mounted" value="true">
 <ivm:Option name="exec" \
      value="echo naughty.notify\({timeout=15,\ title=\'Mounted\',\
      text=\'$hal.block.device$ at $hal.volume.mount_point$ \($hal.volume.size$\)\'}\)\
      | awesome-client -" />
</ivm:Match>
       
<ivm:Match name="hal.info.category" value="storage">
 <ivm:Match name="hal.storage.drive_type" value="disk">
  <ivm:Option name="exec" value="echo naughty.notify\({timeout=15, title=\'New Volume\',\
       text=\'$hal.info.vendor$ $hal.info.product$ $hal.storage.size$\'}\) | awesome-client -" />
 </ivm:Match>
</ivm:Match>

rc.lua + curl / hack for *WRT/AutoAP network switch[edit]

AutoAP is a daemon script allowing OpenWRT/DD-WRT/etc. switch networks according to signal quality which is additionally monitored with ping. See DD-WRT Wiki for more info.

function dump_autoap()
   os.execute('curl -s http://gw/user/autoap.htm  > /tmp/.awesome.autoap &')
end

last_ap = "none"
function get_autoap()
   local ap = ""
   if info then return end
   local f = io.open('/tmp/.awesome.autoap')
   if not f then return end
   local line = f:read()
   f:close()
   if not line then return end

   local aar, beg = line:find('<title>')
   if line:sub(beg+32, beg+32) == 'S' then ap = "<span color=\"#FF602E\">searching...</span>"
   elseif line:sub(beg+32,beg+32) == 'C' then
      endd = line:find('</title>', beg)
      ap = line:sub(beg+47,endd-2)
   end

   if ap ~= last_ap then 
     naughty.notify({title = "AutoAP network", text = ap, timeout = 10})
     last_ap = ap 
   end
   return ap
end

function hook_10s()
  dump_autoap()
  get_autoap()
end

awful.hooks.timer.register(10, hook_10s)

rc.lua + dict / dictionary prompt with naughty output[edit]

keybinding({ modkey}, "d", function ()
        info = true
        awful.prompt.run({ fg_cursor = "black",bg_cursor="orange", prompt = "<span color='#008DFA'>Dict:</span> " }, 
        mypromptbox[mouse.screen],
        function(word)
                local f = io.popen("dict -d wn " .. word .. " 2>&1")
                local fr = ""
                for line in f:lines() do
                fr = fr .. line .. '\n'
                end
                f:close()
                naughty.notify({ text = '<span font_desc="Sans 7">'..fr..'</span>', timeout = 0, width = 400 })
        end,
        nil, awful.util.getdir("cache") .. "/dict") 
end):add()

rc.lua / calculator prompt with naughty output[edit]

The below keybinding displays a calculator prompt (prefilled with the last result if exists) and displays a naughty popup with value of the expression. When clicked, the value is copied to the clipboard for pasting somewhere else. screenshot

val = nil
keybinding({ modkey}, "c", function ()
    awful.prompt.run({  text = val and tostring(val),
            selectall = true,
            fg_cursor = "black",bg_cursor="orange",
            prompt = "<span color='#00A5AB'>Calc:</span> " }, mypromptbox,
            function(expr)
              val = awful.util.eval(expr)
              naughty.notify({ text = expr .. ' = <span color="white">' .. val .. "</span>",
                               timeout = 0,
                               run = function() io.popen("echo ".. val .. " | xsel -i"):close() end, })
            end,
            nil, awful.util.getdir("cache") .. "/calc")
end):add()

Using naughty for debugging lua code[edit]

With naughty it's very simple to check value of variables at any time you want. Forget print() and checking the console. To save yourself hassle of full syntax, you can put this function before the code you want to debug:

function dbg(vars)
    local text = ""
    for i=1, #vars do text = text .. vars[i] .. " | " end
    naughty.notify({ text = text, timeout = 0 })
end

Now in the code you want to debug you can use the following line to see values in popups in realtime!

dbg({list, of, variables})

screenshot

Popup calendar[edit]

If you don't have much desktop space and your clock only shows the time, you can have the date/calendar popup on mouse hover. Use your scroll wheel to change the month you are viewing (screenshot)

    local calendar = nil
    local offset = 0

    function remove_calendar()
        if calendar ~= nil then
            naughty.destroy(calendar)
            calendar = nil
            offset = 0
        end
    end

    function add_calendar(inc_offset)
        local save_offset = offset
        remove_calendar()
        offset = save_offset + inc_offset
        local datespec = os.date("*t")
        datespec = datespec.year * 12 + datespec.month - 1 + offset
        datespec = (datespec % 12 + 1) .. " " .. math.floor(datespec / 12)
        local cal = awful.util.pread("cal -m " .. datespec)
        cal = string.gsub(cal, "^%s*(.-)%s*$", "%1")
        calendar = naughty.notify({
            text = string.format('<span font_desc="%s">%s</span>', "monospace", os.date("%a, %d %B %Y") .. "\n" .. cal),
            timeout = 0, hover_timeout = 0.5,
            width = 160,
        })
    end

-- change clockbox for your clock widget (e.g. mytextclock)
    mytextclock:add_signal("mouse::enter", function()
      add_calendar(0)
    end)
    mytextclock:add_signal("mouse::leave", remove_calendar)
 
    mytextclock:buttons(awful.util.table.join(
        button({ }, 4, function()
            add_calendar(-1)
        end),
        button({ }, 5, function()
            add_calendar(1)
        end)
    ))

Feeding naughty via dbus[edit]

Get the latest awesome-git (next branch), naughty will listen on the dbus interface. You can create notifications using notify-me, dbus-send, d-feet or just open any dbus-notification cable application e.g. gajim.

Using notify-send:

notify-send "awesome is" "getting naughty"

Note that on Debian/Ubuntu systems, having the notification-daemon package installed will make notify-send calls be intercepted by Gnome (the notifications won't be displayed by naughty).

Using dbus-send:

dbus-send --dest=org.freedesktop.Notifications /org/freedesktop/Notifications  org.freedesktop.Notifications.Notify string:"" uint32:0 string:"" \
string:"title" string:"text" array:string:"" array:string:"" int32:-1

Suspending/Resuming Naughty[edit]

You can disable naughty temporarily, say when you are watching a movie, by calling naughty.suspend(), and re-enable it later, by calling naughty.resume(). Naughty stores all notifications that were send while it was suspended, and plays them back when resumed.

Replacing Notifications[edit]

Certain events, changing volume for example, may require you to generate popups one after the other immediately. But you don't want these popups to stack together (making the window underneath inaccessible). And Awesome doesn't have the notify-osd yet. Here is a workaround shared by 'psychon' on the users' mailing list:

$ echo 'return naughty.notify({ text = "foo", timeout = 0 }).id' | awesome-client
double 1551
$ echo 'return naughty.notify({ text = "foo2", timeout = 0, replaces_id = 1551 }).id' | awesome-client
double 1552

In essence, replace the previous notification with the newer one.

To be naughtier[edit]