diff --git a/lua/plugins/filetype.lua b/lua/plugins/filetype.lua index 18767ec7d..cc1fd0582 100644 --- a/lua/plugins/filetype.lua +++ b/lua/plugins/filetype.lua @@ -37,9 +37,12 @@ vis.ftdetect.filetypes = { ext = { "%.au3$", "%.a3x$" }, }, awk = { + hashbang = { "^/usr/bin/[mng]awk%s+%-f" }, + utility = { "^[mgn]?awk$", "^goawk$" }, ext = { "%.awk$" }, }, bash = { + utility = { "^[db]ash$", "^sh$","^t?csh$","^zsh$" }, ext = { "%.bash$", "%.csh$", "%.sh$", "%.zsh$" ,"^APKBUILD$", "%.ebuild$"}, mime = { "text/x-shellscript", "application/x-shellscript" }, }, @@ -133,6 +136,7 @@ vis.ftdetect.filetypes = { ext = { "%.fnl$" }, }, fish = { + utility = { "^fish$" }, ext = { "%.fish$" }, }, forth = { @@ -241,15 +245,15 @@ vis.ftdetect.filetypes = { ext = { "%.lgt$" }, }, lua = { + utility = {"^lua%-?5?%d?$", "^lua%-?5%.%d$" }, ext = { "%.lua$" }, mime = { "text/x-lua" }, }, makefile = { + hashbang = {"^#!/usr/bin/make"}, + utility = {"^make$"}, ext = { "%.iface$", "%.mak$", "%.mk$", "GNUmakefile", "makefile", "Makefile" }, mime = { "text/x-makefile" }, - detect = function(_, data) - return data:match("^#!/usr/bin/make") - end }, man = { ext = { @@ -329,6 +333,7 @@ vis.ftdetect.filetypes = { ext = { "%.pure$" }, }, python = { + utility = { "^python%d?" }, ext = { "%.sc$", "%.py$", "%.pyw$" }, mime = { "text/x-python", "text/x-script.python" }, }, @@ -336,6 +341,7 @@ vis.ftdetect.filetypes = { ext = { "%.re$" }, }, rc = { + utility = {"^rc$"}, ext = { "%.rc$", "%.es$" }, }, rebol = { @@ -409,6 +415,7 @@ vis.ftdetect.filetypes = { ext = { "%.taskpaper$" }, }, tcl = { + utility = {"^tclsh$", "^jimsh$" }, ext = { "%.tcl$", "%.tk$" }, }, texinfo = { @@ -536,6 +543,56 @@ vis.events.subscribe(vis.events.WIN_OPEN, function(win) return end end + +--[[ hashbang check + hashbangs only have command argument + if /env, find utility in args + discard first arg if /-[^S]*S/; and all subsequent /=/ + NOTE: this means you can't have a command with /^-|=/ + return first field, which should be the utility. + NOTE: long-options unsupported +--]] + local fullhb, utility = data:match"^#![ \t]*(/+[^/\n]+[^\n]*)" + if fullhb then + local i, field = 1, {} + for m in fullhb:gmatch"%g+" do field[i],i = m,i+1 end + -- NOTE: executables should not have a space (or =, see below) + if field[1]:match"/env$" then + table.remove(field,1) + -- it is assumed that the first argument are short options, with -S inside + if string.match(field[1] or "", "^%-[^S-]*S") then -- -S found + table.remove(field,1) + -- skip all name=value + while string.match(field[1] or "","=") do + table.remove(field,1) + end + -- (hopefully) whatever is left in field[1] should be the utility or nil + end + end + utility = string.match(field[1] or "", "[^/]+$") -- remove filepath + end + + local function searcher(tbl, subject) + for i, pattern in ipairs(tbl or {}) do + if string.match(subject, pattern) then + return true + end + end + return false + end + + if utility or fullhb then + for lang, ft in pairs(vis.ftdetect.filetypes) do + if + utility and searcher(ft.utility, utility) + or + fullhb and searcher(ft.hashbang, fullhb) + then + set_filetype(lang, ft) + return + end + end + end end -- try text lexer as a last resort