mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			144 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| -- a set class for fast union/diff, can always return a table with the lines
 | |
| -- in the same relative order in which they were added by calling the
 | |
| -- to_table method. It does this by keeping two lua tables that mirror each
 | |
| -- other:
 | |
| -- 1) index => item
 | |
| -- 2) item => index
 | |
| local Set = {}
 | |
| 
 | |
| function Set:new(items)
 | |
|   local obj = {}
 | |
|   setmetatable(obj, self)
 | |
|   self.__index = self
 | |
| 
 | |
|   if type(items) == 'table' then
 | |
|     local tempset = Set:new()
 | |
|     tempset:union_table(items)
 | |
|     obj.tbl = tempset:raw_tbl()
 | |
|     obj.items = tempset:raw_items()
 | |
|     obj.nelem = tempset:size()
 | |
|   else
 | |
|     obj.tbl = {}
 | |
|     obj.items = {}
 | |
|     obj.nelem = 0
 | |
|   end
 | |
| 
 | |
|   return obj
 | |
| end
 | |
| 
 | |
| function Set:copy()
 | |
|   local obj = {}
 | |
|   obj.nelem = self.nelem
 | |
|   obj.tbl = {}
 | |
|   obj.items = {}
 | |
|   for k, v in pairs(self.tbl) do
 | |
|     obj.tbl[k] = v
 | |
|   end
 | |
|   for k, v in pairs(self.items) do
 | |
|     obj.items[k] = v
 | |
|   end
 | |
|   setmetatable(obj, Set)
 | |
|   obj.__index = Set
 | |
|   return obj
 | |
| end
 | |
| 
 | |
| -- adds the argument Set to this Set
 | |
| function Set:union(other)
 | |
|   for e in other:iterator() do
 | |
|     self:add(e)
 | |
|   end
 | |
| end
 | |
| 
 | |
| -- adds the argument table to this Set
 | |
| function Set:union_table(t)
 | |
|   for _, v in pairs(t) do
 | |
|     self:add(v)
 | |
|   end
 | |
| end
 | |
| 
 | |
| -- subtracts the argument Set from this Set
 | |
| function Set:diff(other)
 | |
|   if other:size() > self:size() then
 | |
|     -- this set is smaller than the other set
 | |
|     for e in self:iterator() do
 | |
|       if other:contains(e) then
 | |
|         self:remove(e)
 | |
|       end
 | |
|     end
 | |
|   else
 | |
|     -- this set is larger than the other set
 | |
|     for e in other:iterator() do
 | |
|       if self.items[e] then
 | |
|         self:remove(e)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 | |
| 
 | |
| function Set:add(it)
 | |
|   if not self:contains(it) then
 | |
|     local idx = #self.tbl + 1
 | |
|     self.tbl[idx] = it
 | |
|     self.items[it] = idx
 | |
|     self.nelem = self.nelem + 1
 | |
|   end
 | |
| end
 | |
| 
 | |
| function Set:remove(it)
 | |
|   if self:contains(it) then
 | |
|     local idx = self.items[it]
 | |
|     self.tbl[idx] = nil
 | |
|     self.items[it] = nil
 | |
|     self.nelem = self.nelem - 1
 | |
|   end
 | |
| end
 | |
| 
 | |
| function Set:contains(it)
 | |
|   return self.items[it] or false
 | |
| end
 | |
| 
 | |
| function Set:size()
 | |
|   return self.nelem
 | |
| end
 | |
| 
 | |
| function Set:raw_tbl()
 | |
|   return self.tbl
 | |
| end
 | |
| 
 | |
| function Set:raw_items()
 | |
|   return self.items
 | |
| end
 | |
| 
 | |
| function Set:iterator()
 | |
|   return pairs(self.items)
 | |
| end
 | |
| 
 | |
| function Set:to_table()
 | |
|   -- there might be gaps in @tbl, so we have to be careful and sort first
 | |
|   local keys
 | |
|   do
 | |
|     local _accum_0 = { }
 | |
|     local _len_0 = 1
 | |
|     for idx, _ in pairs(self.tbl) do
 | |
|       _accum_0[_len_0] = idx
 | |
|       _len_0 = _len_0 + 1
 | |
|     end
 | |
|     keys = _accum_0
 | |
|   end
 | |
|   table.sort(keys)
 | |
|   local copy
 | |
|   do
 | |
|     local _accum_0 = { }
 | |
|     local _len_0 = 1
 | |
|     for _index_0 = 1, #keys do
 | |
|       local idx = keys[_index_0]
 | |
|       _accum_0[_len_0] = self.tbl[idx]
 | |
|       _len_0 = _len_0 + 1
 | |
|     end
 | |
|     copy = _accum_0
 | |
|   end
 | |
|   return copy
 | |
| end
 | |
| 
 | |
| return Set
 | 
