feat: proper CLI usage in main
							parent
							
								
									1d21442e4f
								
							
						
					
					
						commit
						d526238ee5
					
				
							
								
								
									
										156
									
								
								main.lua
								
								
								
								
							
							
						
						
									
										156
									
								
								main.lua
								
								
								
								
							| 
						 | 
					@ -1,28 +1,140 @@
 | 
				
			||||||
#!/bin/env lua
 | 
					#!/bin/env lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local html = require(".html")
 | 
					local HTML = require(".html")
 | 
				
			||||||
local css = require(".css")
 | 
					local CSS = require(".css")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local logger = require(".logging")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local file = io.open("small.html", "r")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if file == nil then
 | 
					
 | 
				
			||||||
	error("File doesn't exist")
 | 
					local function file_exists(name)
 | 
				
			||||||
 | 
					   local f=io.open(name,"r")
 | 
				
			||||||
 | 
					   if f~=nil then io.close(f) return true else return false end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local content = file:read("a")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
local doc = html.parse( content )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
print("Write a css selector:")
 | 
					local function print_usage()
 | 
				
			||||||
local whole_selector = css.parse( io.read() )
 | 
					    logger.print("Usage: lua main.lua [FLAGS] <html_path_or_minus> <css_selector>")
 | 
				
			||||||
local current_selector = whole_selector
 | 
					    logger.print("  html_path_or_minus: Path to HTML file or '-' for stdin")
 | 
				
			||||||
 | 
					    logger.print("  css_selector: CSS selector to search for")
 | 
				
			||||||
 | 
							logger.print()
 | 
				
			||||||
 | 
							logger.print("  Flags:")
 | 
				
			||||||
 | 
					    logger.print("  -f, --first-only: return only the first match")
 | 
				
			||||||
 | 
					    logger.print("  -q, --quiet: Don't print warnings")
 | 
				
			||||||
 | 
					    os.exit(1)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local FLAGS = {
 | 
				
			||||||
 | 
						FIRST_ONLY = {},
 | 
				
			||||||
 | 
						NO_PRINT_ERRORS = {},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local LONGHAND_FLAGS = {
 | 
				
			||||||
 | 
						["first-only"] = FLAGS.FIRST_ONLY,
 | 
				
			||||||
 | 
						["quiet"] = FLAGS.NO_PRINT_ERRORS
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local SHORTHAND_FLAGS = {
 | 
				
			||||||
 | 
						["f"] = FLAGS.FIRST_ONLY,
 | 
				
			||||||
 | 
						["q"] = FLAGS.NO_PRINT_ERRORS,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if #arg < 2 then
 | 
				
			||||||
 | 
						logger.printerr("Error: Not enough arguments")
 | 
				
			||||||
 | 
						print_usage()
 | 
				
			||||||
 | 
						return 1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local flags = {}
 | 
				
			||||||
 | 
					local positionals = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for _, argument in ipairs(arg) do
 | 
				
			||||||
 | 
						if argument:match("^%-%w+$") then
 | 
				
			||||||
 | 
							for letter in argument:sub(2):gmatch("(%w)") do
 | 
				
			||||||
 | 
								if not SHORTHAND_FLAGS[letter] then
 | 
				
			||||||
 | 
									logger.printerr("Unknown flag: -"..letter..".")
 | 
				
			||||||
 | 
									print_usage()
 | 
				
			||||||
 | 
									return 1
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								local flag = SHORTHAND_FLAGS[letter]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if flags[flag] then
 | 
				
			||||||
 | 
									logger.printerr("Warning: passed -" .. letter .. " flag already !")
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								flags[flag] = true
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						elseif argument:match("^%-%-[%w%-]+$") then
 | 
				
			||||||
 | 
							local flagname = argument:sub(3)
 | 
				
			||||||
 | 
							if not LONGHAND_FLAGS[flagname] then
 | 
				
			||||||
 | 
								logger.printerr("Unknown flag: --"..flagname..".")
 | 
				
			||||||
 | 
								print_usage()
 | 
				
			||||||
 | 
								return 1
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							local flag = LONGHAND_FLAGS[flagname]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if flags[flag] then
 | 
				
			||||||
 | 
								logger.printerr("Warning: passed --" .. flagname .. " flag already !")
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							flags[flag] = true
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							table.insert( positionals, argument )
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if not flags[ FLAGS.NO_PRINT_ERRORS ] then
 | 
				
			||||||
 | 
						logger.enable_printing_errors()
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if #positionals > 2 then
 | 
				
			||||||
 | 
						logger.printerr("Error: too many arguments !")
 | 
				
			||||||
 | 
						print_usage()
 | 
				
			||||||
 | 
						return 1
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local html_file = positionals[1]
 | 
				
			||||||
 | 
					local html = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if html_file ~= "-" then
 | 
				
			||||||
 | 
						if not( file_exists( html_file )) then
 | 
				
			||||||
 | 
							logger.printerr("File doesn't exist: " .. html_file)
 | 
				
			||||||
 | 
							return 2
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local handle = io.open( html_file, "r" )
 | 
				
			||||||
 | 
						if not handle then
 | 
				
			||||||
 | 
							logger.printerr("Failed to open file " .. html_file)
 | 
				
			||||||
 | 
							return 2
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						html = handle:read("a")
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						html = io.read()
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local document = HTML.parse( html )
 | 
				
			||||||
 | 
					local css_selector = CSS.parse( positionals[2] )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local current_selector = css_selector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local elements = {}
 | 
					local elements = {}
 | 
				
			||||||
-- start with all elements matching the first selector
 | 
					-- start with all elements matching the first selector
 | 
				
			||||||
doc:foreach(function( el )
 | 
					document:foreach(function( el )
 | 
				
			||||||
	if el:check_simple_selector( current_selector.selector ) then
 | 
						if el:check_simple_selector( current_selector.selector ) then
 | 
				
			||||||
		table.insert( elements, el )
 | 
							table.insert( elements, el )
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
| 
						 | 
					@ -33,7 +145,7 @@ while current_selector.combinator ~= nil do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local new_elements = {}
 | 
						local new_elements = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if current_selector.combinator == css.COMBINATORS.DESCENDANT then
 | 
						if current_selector.combinator == CSS.COMBINATORS.DESCENDANT then
 | 
				
			||||||
		for _, element in ipairs( elements ) do
 | 
							for _, element in ipairs( elements ) do
 | 
				
			||||||
			element:foreach(function( el )
 | 
								element:foreach(function( el )
 | 
				
			||||||
				if el:check_simple_selector( next_selector.selector ) then
 | 
									if el:check_simple_selector( next_selector.selector ) then
 | 
				
			||||||
| 
						 | 
					@ -45,7 +157,7 @@ while current_selector.combinator ~= nil do
 | 
				
			||||||
		goto continue
 | 
							goto continue
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if current_selector.combinator == css.COMBINATORS.DIRECT_DESCENDANT then
 | 
						if current_selector.combinator == CSS.COMBINATORS.DIRECT_DESCENDANT then
 | 
				
			||||||
		for _, element in ipairs( elements ) do
 | 
							for _, element in ipairs( elements ) do
 | 
				
			||||||
			for _, child in ipairs( element.children ) do
 | 
								for _, child in ipairs( element.children ) do
 | 
				
			||||||
				if child:check_simple_selector( next_selector.selector ) then
 | 
									if child:check_simple_selector( next_selector.selector ) then
 | 
				
			||||||
| 
						 | 
					@ -57,7 +169,7 @@ while current_selector.combinator ~= nil do
 | 
				
			||||||
		goto continue
 | 
							goto continue
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if current_selector.combinator == css.COMBINATORS.NEXT_SIBLING then
 | 
						if current_selector.combinator == CSS.COMBINATORS.NEXT_SIBLING then
 | 
				
			||||||
		for _, element in ipairs( elements ) do
 | 
							for _, element in ipairs( elements ) do
 | 
				
			||||||
			local next_sibling = element:get_next_sibling()
 | 
								local next_sibling = element:get_next_sibling()
 | 
				
			||||||
			while next_sibling and next_sibling.tag_name == ":text" do
 | 
								while next_sibling and next_sibling.tag_name == ":text" do
 | 
				
			||||||
| 
						 | 
					@ -72,7 +184,7 @@ while current_selector.combinator ~= nil do
 | 
				
			||||||
		goto continue
 | 
							goto continue
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if current_selector.combinator == css.COMBINATORS.SUBSEQUENT_SIBLING then
 | 
						if current_selector.combinator == CSS.COMBINATORS.SUBSEQUENT_SIBLING then
 | 
				
			||||||
		for _, element in ipairs( elements ) do
 | 
							for _, element in ipairs( elements ) do
 | 
				
			||||||
			local sibling = element:get_next_sibling()
 | 
								local sibling = element:get_next_sibling()
 | 
				
			||||||
			while sibling ~= nil do
 | 
								while sibling ~= nil do
 | 
				
			||||||
| 
						 | 
					@ -96,10 +208,14 @@ end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if flags[FLAGS.FIRST_ONLY] then
 | 
				
			||||||
 | 
						if #elements > 0 then
 | 
				
			||||||
 | 
							logger.print( HTML.tostring( elements[1] ) )
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
for _, el in ipairs(elements) do
 | 
						return 0
 | 
				
			||||||
	print( html.tostring( el ) )
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for _, el in ipairs(elements) do
 | 
				
			||||||
 | 
							logger.print( HTML.tostring(el) )
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue