From da51b3697e37d916e43fa61d64e7876835feb120 Mon Sep 17 00:00:00 2001 From: Guilian Date: Sun, 19 Jan 2025 14:18:43 +0100 Subject: [PATCH] feat: proper CLI usage in main --- main.lua | 156 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 20 deletions(-) diff --git a/main.lua b/main.lua index ca4d825..380d2fc 100644 --- a/main.lua +++ b/main.lua @@ -1,28 +1,140 @@ #!/bin/env lua -local html = require(".html") -local css = require(".css") +local HTML = require(".html") +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 -local content = file:read("a") - -local doc = html.parse( content ) -print("Write a css selector:") -local whole_selector = css.parse( io.read() ) -local current_selector = whole_selector +local function print_usage() + logger.print("Usage: lua main.lua [FLAGS] ") + 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 = {} -- 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 table.insert( elements, el ) end @@ -33,7 +145,7 @@ while current_selector.combinator ~= nil do 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 element:foreach(function( el ) if el:check_simple_selector( next_selector.selector ) then @@ -45,7 +157,7 @@ while current_selector.combinator ~= nil do goto continue 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 _, child in ipairs( element.children ) do if child:check_simple_selector( next_selector.selector ) then @@ -57,7 +169,7 @@ while current_selector.combinator ~= nil do goto continue 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 local next_sibling = element:get_next_sibling() while next_sibling and next_sibling.tag_name == ":text" do @@ -72,7 +184,7 @@ while current_selector.combinator ~= nil do goto continue 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 local sibling = element:get_next_sibling() 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 - print( html.tostring( el ) ) + return 0 end - - +for _, el in ipairs(elements) do + logger.print( HTML.tostring(el) ) +end