hchunhui / librime-lua

Extending RIME with Lua scripts
BSD 3-Clause "New" or "Revised" License
347 stars 43 forks source link

Add load config from all lua files of a directory #151

Open CoelacanthusHex opened 2 years ago

CoelacanthusHex commented 2 years ago

As title, I want to add a feature, which can load config files from all lua files in a specified directory such as $sharedir/lua.conf.d and $userdir/lua.conf.d. It is helpful for creating and using lua scripts packaged into system packages(e .g. aur package of https://github.com/hchunhui/librime-cloud ), we can just put the lua script in specified directory, and it will work well. (Now we have to create a hook to auto generate a big file include all contexts, and it is not suitable for all systems so we have to create different hook for different system(even some system have no hook feature, users have to do themselves). So we need a general solution built in librime-lua to have same behavior in all systems.) PS: I suggest librime-lua don't load files recursively, because some lua scripts may have a directory to store libs like your librime-cloud.

shewer commented 2 years ago

不建議 除非 是必要且共用的library 且只能載入到 global 且 固定變數名

-- 在 shared_data/lua   , user_data/lua  增加  conf_dir  將 lua file 放在路逕下
local function load_conf( data_dir )
  local lib_path= "conf_dir"  -- lua/config_dir
  local ch = package.config:sub(1,1)  -- uinx =/  win = \
  local cmd = ch:match("/") and "ls " or "dir "
  -- ls   [data_dir]/lua/[lib_path]/*.lua
  local fullpath= table.concat( {data_dir,"lua",lib_path, "*.lua" },ch)
  for file in io.popen(cmd .. fullpath):lines() do

  --   [data_dir]/lua/[lib_path]/xxx.lua  -->  [lib_path]/xxx
   local pattern = ("^.*%s(%s%s.*)[.]lua$"):format(ch,lib_path,ch)
   local rfile = file:match(pattern)
   print( "require ", rfile)
   --   require(rfile)  --  載入 模組
  end
end
-- load  shared_data_dir   user_data_dir
for i, path in ipairs(
  {rime_api.get_user_data_dir(), rime_api.get_shared_data_dir() })  do
  load_conf(path)
end

—[[ 
require   conf_dir/conjunctive
require   conf_dir/in
require   conf_dir/processor_init
require   conf_dir/p_test
require   conf_dir/reorder
require   conf_dir/testp
require   conf_dir/utf88
require   conf_dir/vv
require   conf_dir/conjunctive
require   conf_dir/in
require   conf_dir/processor_init
—]]
hchunhui commented 2 years ago

@CoelacanthusHex Yes, it makes sense. But I think it's too restrictive if we just load all lua files in lua.conf.d. The auto-loading will pollute the global environment of lua.

@shewer 's solution is better. We can ship a default $sharedir/rime.lua that looks like the above, so that all lua scripts can be loaded by default. For advanced users, they can customize the loading procedure by writing their own $userdir/rime.lua.

The only issue is lua can not iterater files in a directory, so the above script contains some ugly hacks. To address the issue, I think we can add an API called iterater_conf_files(), it will return an iterator of all lua files in lua.conf.d. The default rime.lua looks like the following:

for file in iterator_conf_files():
    -- load the file...
end
CoelacanthusHex commented 2 years ago

@hchunhui I think your solution is better than mine. Please do it. When it has done, I will change packages managed by me on AUR.

shewer commented 2 years ago

rime_api 本身就是 table 可以在 rime_api 內增加 conf_files() 但是 lua.conf.d 不在 package.path 無法使用 require

-- rime_api.lua
function rime_api.conf_files()
  local ch = package.config:sub(1,1)  -- uinx =/  win = \
  local cmd = ch:match("/") and "ls " or "dir "

  local share_conf_dir =  rime_api.get_shared_data_dir() .. ch .. 
 "lua.conf.d"
   local user_conf_dir = rime_api.get_user_data_dir() .. ch .. "lua.conf.d"

   local files ={}
   for path in  next , { share_conf_dir, user_conf_dir} do 
      for file in io.popen(cmd .. path):lines() do
           table.insert(files,file)
      end
    end 
    return  coroutine.wrap( function()
            for i,file in ipairs( files) do 
                   coroutine.yield(file)
             end
     end)
end 

-- rime.lua
require 'rime_api'

for file in rime_api.conf_files() do 
     ---  full file name of string
end
hchunhui commented 2 years ago

@hchunhui I think your solution is better than mine. Please do it. When it has done, I will change packages managed by me on AUR.

@CoelacanthusHex Finally we have a different way to achieve the same goal in #189, please see the documentation.