玩awesome学lua# autostart模块

随着一个桌面环境启动的同时启动一些必备的程序。诸如:输入法之类。很多地方这种实现叫做autostart,我也觉的很贴切。

aweome的wiki里有一段关于autostart纯lua实现的代码片段,为了简洁和便于使用,我将其改成了模块,添加了新的使用接口。

并添加到rc.lua

require("autostart")
autostart.run_once_list{
    "wmname LG3D",
    "fcitx",
    "clipit",
    "lanuchy",
    "guake -e ranger",
    "batti",
    "firefox",
    "amule",
}

下面是修改成模块的autostart.lua,放在~/.config/awesome/下面

基本的原理是遍历/proc下表示一个个进程目录,通过每个进程目录下cmdline去判断想要的程序是否已经启动,没有则执行相应的启动命令

这段程序涉及到不少lua的基础知识,简单总结下:

  • 模块的使用和创建以及模块内的可见性;
  • 协同程序实现的迭代器;
  • unpack的使用;
  • string.find / string.gsub 的使用;
  • io模块的使用;

另外:lfs模块需要安装luafilesystem获得

require("lfs") 
module("autostart",package.seeall)
-- {{{ Run programm once
function processwalker()
   local function yieldprocess()
      for dir in lfs.dir("/proc") do
        -- All directories in /proc containing a number, represent a process
        if tonumber(dir) ~= nil then
          local f, err = io.open("/proc/"..dir.."/cmdline")
          if f then
            local cmdline = f:read("*all")
            f:close()
            if cmdline ~= "" then
              coroutine.yield(cmdline)
            end
          end
        end
      end
    end
    return coroutine.wrap(yieldprocess)
end

function run_once(process, cmd)
   assert(type(process) == "string")
   local regex_killer = {
      ["+"]  = "%+", ["-"] = "%-",
      ["*"]  = "%*", ["?"]  = "%?" }

   for p in processwalker() do
      if p:find(process:gsub("[-+?*]", regex_killer)) then
     return
      end
   end
   return awful.util.spawn_with_shell(cmd or process)
end

function run_once_list(list)
    parse(list,run_once)
end

function parse(list,fn)
    for k,v in ipairs(list)do
        if type(v) == "string" then
            v={v}
        end
        fn(unpack(v))
    end
end
--
-- Use the second argument, if the programm you wanna start, 
-- differs from the what you want to search.
--run_once("redshift", "nice -n19 redshift -l 51:14 -t 5700:4500")