summaryrefslogtreecommitdiffstats
path: root/lib/menubuilder.lua
blob: 6def1fe7a5ca51d77c3d62de9d3a87f6209b6262 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
--[[ parse through the *.menu tables and return a "menu" table
     Written for Alpine Configuration Framework (ACF) -- see www.alpinelinux.org
     Copyright (C) 2007  Nathan Angelacos
     Licensed under the terms of GPL2
  ]]--
module(..., package.seeall)

-- returns a table of the "*.menu" tables 
-- uses the system "find" command
-- startdir should be the app dir.
local get_candidates = function (startdir)
	local t = {}
	startdir = startdir .. "/"
	local fh = io.popen('find ' .. startdir .. ' -name "*.menu"')

	local start = string.gsub(startdir, "/$", "")
	for x in fh:lines() do
		table.insert (t, (string.gsub(x, start, "")))
	end

	return t
end


-- internal function for table.sort
local t_compare = function  (x,y,f)
		for k,v in pairs(f) do
			local a = x[v]  
			local b = y[v] 
			if tonumber(a) and tonumber(b) then
				a=tonumber(a) 
				b=tonumber(b) 
			end
			if a < b then return true end
			if a > b then return false end
		end
		return false
		end


-- returns a table of all the menu items found, sorted by priority
-- Table format:   prefix  controller  cat group tab action
get_menuitems = function (startdir)
	local t = {}
	for k,v in pairs(get_candidates(startdir)) do
		local prefix, controller = mvc.dirname(v), mvc.basename(v, ".menu")
		-- open the thing, and parse the contents
		local fh = io.open(startdir .. "/" .. v)
		local prio = 10
		for x in fh:lines() do
			if not string.match(x, "^#")  then
				local item = {}
				for i in string.gmatch(x, "%S+") do
					table.insert(item, i)
				end
				table.insert(t, { prefix=prefix, 
						  controller=controller, 
						  catprio="nan",
						  cat=item[1] or "",
						  groupprio="nan", 
						  group=item[2] or "",
						  tabprio=tostring(prio),
						  tab=item[3] or "",
						  action=item[4] or "" })
				prio=prio+5
			end
		end
		fh:close()	
	end
	-- Ok, we now have the raw menu table 
	-- now try to parse out numbers in front of any cat, group or tabs
	for x in ipairs(t) do
		local f = t[x]
		if (string.match(f.cat, "^%d")) then
			f.catprio, f.cat = string.match(f.cat, "(%d+)(.*)")
		end
		if (string.match(f.group, "^%d")) then
			f.groupprio, f.group = string.match(f.group, "(%d+)(.*)")
		end
		if (string.match(f.tab, "^%d")) then
			f.tabprio, f.tab = string.match(f.tab, "(%d+)(.*)")
		end
	end

	-- Convert underscores to spaces
	for x in ipairs(t) do
		t[x].cat = string.gsub(t[x].cat, "_", " ")
		t[x].group = string.gsub(t[x].group, "_", " ")
		t[x].tab = string.gsub(t[x].tab, "_", " ")
	end

	-- Now alpha sort
	table.sort(t, function(x,y)
		return t_compare (x,y,{"cat", "catprio", "group", "groupprio", "tab", "tabprio"} )
		end)

	-- Fill in the priorities
	local fill_prio = function (t, start, stop, col)
		local prio = t[start][col] 
		if prio == "nan" then prio = "0" end
		while start <= stop do
			t[start][col] = prio
			start = start + 1
		end
	end


-- Fill in the priorities
-- Warning - UGLY code ahead.
-- Basic rules, for each cat and group, if the prio is nan, then set it
-- to the lowest value for that group or cat.  
 	local k = 1
	while ( k <= table.maxn(t) ) do
		local c = k
		while ( c <= table.maxn(t) and t[c].cat == t[k].cat ) do 
			c=c+1 
			end
		c=c-1 -- back up one - we only want whats the same
		fill_prio(t,k,c,"catprio")
		-- from k,c is a mini table, do the same for groupprio
		local g = k
		while ( g <= c ) do
			local h = g
			while ( h <= c and t[h].group == t[g].group ) do
				h=h+1
			end
			h=h-1 --- back up one (again)
			fill_prio(t,g,h,"groupprio")
			g=h+1
		end
		k = c + 1
	end
	
	-- Now priority sort
	table.sort(t, function(x,y)
		return t_compare (x,y,{"catprio", "cat", "groupprio", "group", "tabprio", "tab"} )
		end)


	-- drop the priorities - they were internal
	for k,v in ipairs(t) do
		v.catprio = nil
		v.groupprio = nil
		v.tabprio = nil
	end

	return t
end