seaofvoices / darklua

A command line tool that transforms Lua code
https://darklua.com/
MIT License
78 stars 10 forks source link

Append license comment rule #122

Closed jeparlefrancais closed 9 months ago

jeparlefrancais commented 1 year ago

Create a rule that can append a given license at the beginning of each processed file. Something like:

{
  rule: "append_text_comment",
  // either
  text: "text to append",
  // or
  file: "LICENSE.txt"
}
bainchild commented 1 year ago

Maybe generalize this to any text, including lua(u) code? Prepending code could be used to do setup/environment checks, although it would make the rule to inject globals redundant (except for clarity). Also to specify if the code is being processed, a parameter for when to prepend the file (before/after processing). Not sure if this widens the scope of darklua too much, following the unix philosophy...

jeparlefrancais commented 1 year ago

I'm not against a rule that could prefix files with some Lua code, but I'd make it a separate rule from this one. For security concerns, I think it's preferable to force the content to be commented out in case it's coming from something dynamic.

Also, I'm curious if you have a specific use case behind this, as it may be a good idea for a more specific rule. The use case of globals injection is a good example of that

bainchild commented 1 year ago

I think separating comments and code is a good idea. My specific use case is to generalize environment-specific functions, & otherwise check for capabilities. ex:

-- generalizing environment functions
local http_get
if env=="Roblox" then
   http_get=function(url) return game:GetService("HttpService"):GetAsync(url) end
elseif env=="ComputerCraft" then
   http_get=function(url)
      local handle = http.get(url)
      local content = handle.readAll()
      handle.close()
      return content
   end
--elseif env==...
end
if http_get then
   print(http_get('https://example.com'))
else
   error('No http function!')
end

-- optional environment setup
if INTERPRETER and type(INTERPRETER)=="table" and rawget(INTERPRETER,"load") then
   pcall(INTERPRETER.load,INTERPRETER,"metasafety")
end
--> work with objects safely, by telling the
--interpreter to use rawget, rawset, and typechecks
--to ensure that you don't trigger any metamethods
--without an error. For security reasons. 

I think my use case (execution in uncertain environments) is too specific for a rule that is worth the complexity for more than like, 5 people. Also once you have to do something like this, simple rule ordering might not be enough, and you may prefer a full preprocess stage.

jeparlefrancais commented 1 year ago

What I would recommend for a use-case like this is to encapsulate the environment specific functions into their own files. For example, for a project where I want to support Lune and Roblox, I created a json.lua file to handle the environment specific functions.

if _G.ENV == "roblox" then
    local HttpService = game:GetService('HttpService') :: HttpService

    local function encode(value: unknown)
        return HttpService:JSONEncode(value)
    end

    return {
        encode = encode,
    }
end

local net = require('@lune/net')

local function encode(value: unknown)
    return net.jsonEncode(value)
end

return {
    encode = encode,
}

Then that way, I don't have to branch in all the places where I need this. I can just require my own interface and it's good to go. It is also pretty easy to extend and support more platforms if needed!

bainchild commented 1 year ago

It was only in 1 file for the example. In practice I do separate environment-specific functions into different files, then insert them into 1 file using a preprocess stage in the right branch. I think all the uses of the prepending code version of this rule could be solved by inlining/partial imports, which I feel are out of scope for darklua.