-- SCL (Siemens Structured Control Language) support for Neovim -- Main setup module local M = {} function M.setup(opts) opts = opts or {} M.create_commands() -- Treesitter parser config local has_ts, ts = pcall(require, "nvim-treesitter.parsers") if has_ts and ts.get_parser_configs then local ok, parser_config = pcall(ts.get_parser_configs) if ok and parser_config then parser_config.scl = { install_info = { files = { "src/parser.c" }, generate_requires_npm = false, requires_generate_from_grammar = false, }, filetype = "scl", } end end -- Register blink.cmp source if opts.cmp then local function try_register() local cmp_ok, cmp = pcall(require, "blink.cmp") if cmp_ok and cmp and cmp.add_source_provider then local source_config = { name = "scl", module = "scl.blink_cmp_source", score_offset = 100, } pcall(cmp.add_source_provider, "scl", source_config) pcall(cmp.add_filetype_source, "scl", "scl") -- Create autocmd to trigger completion on ( for SCL files local augroup = vim.api.nvim_create_augroup("SCLCompletionTrigger", { clear = true }) vim.api.nvim_create_autocmd("TextChangedI", { group = augroup, pattern = "*.scl", callback = function(args) local line = vim.api.nvim_get_current_line() local col = vim.api.nvim_win_get_cursor(0)[2] -- Check if the character before cursor is ( if col > 0 and line:sub(col, col) == "(" then -- Check if there's a known FB variable before the ( local before_paren = line:sub(1, col - 1):match("[%w_]+%s*$") if before_paren then vim.schedule(function() pcall(require("blink.cmp").show, { providers = { "scl" } }) end) end end end, }) vim.notify("SCL: blink.cmp source registered", vim.log.levels.INFO) return true end return false end if not try_register() then vim.api.nvim_create_autocmd("BufEnter", { pattern = "*.scl", once = true, callback = try_register, }) end end -- Workspace type scanner if opts.workspace_types ~= false then local workspace_types = require("scl.workspace_types") workspace_types.setup({ project_root = opts.project_root, library_paths = opts.library_paths, debug = opts.debug, }) end -- Auto-prefixing (enabled by default) M.setup_auto_prefix() -- Multiline parameters feature M.setup_multiline_params() end function M.setup_multiline_params() local mp = require("scl.multiline_params") vim.api.nvim_create_user_command("SCLMultilineParams", function() mp.fill_multiline_params() end, {}) vim.keymap.set("i", "mp", function() mp.fill_multiline_params() end, { noremap = true, silent = true, desc = "SCL: Fill multiline parameters" }) vim.keymap.set("i", "", function() local ft = vim.bo.filetype if ft == "scl" or ft == "udt" then if mp.jump_to_next_param() then return "" end end return "" end, { noremap = true, silent = true, desc = "SCL: Jump to next param or Tab" }) end function M.setup_auto_prefix() require("scl.auto_prefix").setup() end function M.prefix_current_word() require("scl.auto_prefix").prefix_word() end function M.show_variables() local vars = require("scl.variables").extract_variables() if #vars == 0 then vim.notify("No local variables found", vim.log.levels.INFO) return end local lines = { "Local Variables:", "---" } for _, var in ipairs(vars) do local type_info = var.type and (" : " .. var.type) or "" table.insert(lines, "#" .. var.name .. type_info) end vim.notify(table.concat(lines, "\n"), vim.log.levels.INFO) end function M.show_workspace_types() local ws = require("scl.workspace_types") local udt = require("scl.udt_parser") local fb = require("scl.fb_parser") local root = ws.get_project_root() local udt_names = udt.get_all_udt_names() local fb_names = fb.get_all_fb_names() if not root then vim.notify("No project root detected", vim.log.levels.WARN) return end vim.notify("Project: " .. root .. "\nUDTs: " .. #udt_names .. "\nFBs/Functions: " .. #fb_names, vim.log.levels.INFO) end function M.rescan_workspace_types() local ws = require("scl.workspace_types") local udt = require("scl.udt_parser") local fb = require("scl.fb_parser") udt.clear_cache() fb.clear_cache() ws.clear_root_cache() local udt_result = ws.scan_project_udts() local fb_result = ws.scan_project_fbs() vim.notify("Scanned UDTs: " .. udt_result.parsed_count .. "/" .. udt_result.total_files .. ", FBs: " .. fb_result.parsed_count .. "/" .. fb_result.total_files, vim.log.levels.INFO) end function M.create_commands() vim.api.nvim_create_user_command("SCLShowVariables", function() M.show_variables() end, {}) vim.api.nvim_create_user_command("SCLShowWorkspaceTypes", function() M.show_workspace_types() end, {}) vim.api.nvim_create_user_command("SCLRescanWorkspaceTypes", function() M.rescan_workspace_types() end, {}) end return M