Compare commits

..

21 Commits

Author SHA1 Message Date
Chapaev17 5dab9b2499 feat: updated deepseek configs 2026-05-11 07:29:09 +00:00
root 0f73cbcb92 enhance: improve DeepSeek provider configuration in avante.nvim
Add timeout setting and restructure max_tokens into extra_request_body
for better API request handling and proper configuration structure.
2026-01-27 16:16:18 +00:00
Chapaev17 fc930deb4b Обновить lua/polish/init.lua 2025-10-11 23:16:25 +03:00
User 459fa712d9 refactor: restructure polish module from single file to modular directory format
Signed-off-by: User <user@example.com>
2025-10-11 19:26:47 +00:00
User 6f1adc9381 chore: remove lazy-lock.json from git tracking
- Remove lazy-lock.json from git index while keeping it locally

- File is now properly ignored via .gitignore

- Each user will have their own lazy-lock.json file

Signed-off-by: User <user@example.com>
2025-10-11 19:05:47 +00:00
User 1af2b4cc7d refactor: enhance polish.lua with comprehensive documentation, security validation, and improved error handling
- Add LuaDoc annotations and type definitions for better code documentation

- Implement package name validation to prevent command injection attacks

- Improve error handling with proper notifications and graceful failure handling

- Remove debug prints and make code production-ready

- Add proper module exports for better code organization

- Clean up obsolete lazy_lock_files/vue.json file

Signed-off-by: User <user@example.com>
2025-10-11 19:03:11 +00:00
User 018b471b72 feat: consolidate Mason configuration and add new plugins for enhanced development workflow
- Refactor community.lua module structure for better readability

- Remove obsolete Mason configuration file

- Add new plugins: nvim-lsp-file-operations, nvim-vtsls, package-info.nvim, tsc.nvim

- Implement dynamic Mason package installation based on FRAMEWORK environment variable

- Create custom command 'MasonInstallR' for framework-specific tool installation

Signed-off-by: User <user@example.com>
2025-10-11 16:12:51 +00:00
User 7f725c6530 refactor: improve avante.nvim configuration with better environment variable handling and documentation
- Replace DEEPSEEK_API_KEY check with THIRD_PARTY_AI_ASSISTANT for more flexible AI integration
- Add comprehensive code comments and documentation for better maintainability
- Improve configuration structure and readability
2025-10-11 10:52:20 +00:00
User 508ebdb0c0 feat: enhance dynamic plugin loading with framework support and AI integration
- Update all plugins to latest stable versions

- Add dynamic framework module loading based on FRAMEWORK environment variable

- Support Vue.js and Python framework-specific community modules

- Implement conditional AI plugin activation via DEEPSEEK_API_KEY and THIRD_PARTY_AI_ASSISTANT environment variables

- Improve modularity and configurability of Neovim setup

Signed-off-by: User <user@example.com>
2025-10-11 09:47:27 +00:00
User 4d56666323 chore: remove obsolete Mason configuration files
- Remove python.lua and vue.lua files (replaced by dynamic init.lua)
- Remove mason/.gitignore file
2025-10-10 18:16:50 +00:00
User 306fa774af refactor: consolidate Mason configuration with dynamic framework support
- Replace separate python.lua and vue.lua configs with unified init.lua
- Add dynamic tool installation based on FRAMEWORK environment variable
- Update avante.nvim plugin version from 0.0.23 to 0.0.27
- Remove obsolete mason/.gitignore file
2025-10-10 18:16:38 +00:00
Chapaev17 9a2b77fe5f feat: added dynamic lazy lock 2025-10-10 14:14:20 +00:00
Chapaev17 c0ae23a60d feat: updated astronvim 2025-10-10 09:35:50 +00:00
Chapaev17 d73bcbaa9b feat: change avante and astronvim versions 2025-09-12 11:50:53 +00:00
root c6c794ff7d feat: updated avante 2025-09-05 22:13:43 +00:00
root a42316e692 feat: udpated astronvim 2025-09-05 22:12:35 +00:00
root 4010131ed0 feat: added lazy lock file to gitignore because for different project has different languages and different this file 2025-08-07 18:18:37 +00:00
root b465245c46 feat: added python packages 2025-08-07 18:16:15 +00:00
root b05ed0b5aa feat: disable avante by defatul and added pythoin mason packages 2025-08-07 17:51:08 +00:00
root 8a6bb48755 feat: added pendulum plugin 2025-07-19 00:26:19 +00:00
root 9358f55818 feat: udpated ai parameters 2025-07-18 21:00:43 +00:00
16 changed files with 543 additions and 107 deletions
+1
View File
@@ -0,0 +1 @@
lazy-lock.json
+1 -1
View File
@@ -24,4 +24,4 @@ if not pcall(require, "lazy") then
end end
require "lazy_setup" require "lazy_setup"
require "polish" require "polish.init"
-54
View File
@@ -1,54 +0,0 @@
{
"AstroNvim": { "branch": "main", "commit": "9417da143b971e65b159089c3de5a0ee37edb1fd" },
"Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" },
"LuaSnip": { "branch": "master", "commit": "458560534a73f7f8d7a11a146c801db00b081df0" },
"aerial.nvim": { "branch": "master", "commit": "3284a2cb858ba009c79da87d5e010ccee3c99c4d" },
"astrocommunity": { "branch": "main", "commit": "5f74d5fb8d8dc9b8e2904846809121068d7afaca" },
"astrocore": { "branch": "main", "commit": "c797dd5a592e2bd154f2503e231b8a4083659534" },
"astrolsp": { "branch": "main", "commit": "414775e4b49a46bd7105cc5498ea7bb312359bf2" },
"astrotheme": { "branch": "main", "commit": "f12dcf64b1f9a05839c3ac2146f550f43bae9dab" },
"astroui": { "branch": "main", "commit": "5db873d4af9f6bf57748884bfd4cbccebd4e6863" },
"avante.nvim": { "branch": "main", "commit": "0c6a8f5688cefb37259d3404f0403075e033a182" },
"better-escape.nvim": { "branch": "master", "commit": "199dcc2643dec5d8dbdab4ec672cf405224dcb3b" },
"blink-cmp-avante": { "branch": "master", "commit": "5cf0854b065073083de72d9a988cff1c4b419148" },
"blink.cmp": { "branch": "main", "commit": "3536ce464e82843b00c76718d9bfe1994647d686" },
"blink.compat": { "branch": "main", "commit": "2ed6d9a28b07fa6f3bface818470605f8896408c" },
"cmp-dap": { "branch": "master", "commit": "ea92773e84c0ad3288c3bc5e452ac91559669087" },
"friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" },
"gitsigns.nvim": { "branch": "main", "commit": "7010000889bfb6c26065e0b0f7f1e6aa9163edd9" },
"guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" },
"heirline.nvim": { "branch": "master", "commit": "fae936abb5e0345b85c3a03ecf38525b0828b992" },
"lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" },
"lazydev.nvim": { "branch": "main", "commit": "f59bd14a852ca43db38e3662395354cb2a9b13e0" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "1a31f824b9cd5bc6f342fc29e9a53b60d74af245" },
"mason-null-ls.nvim": { "branch": "main", "commit": "2b8433f76598397fcc97318d410e0c4f7a4bea6a" },
"mason-nvim-dap.nvim": { "branch": "main", "commit": "4c2cdc69d69fe00c15ae8648f7e954d99e5de3ea" },
"mason-tool-installer.nvim": { "branch": "main", "commit": "517ef5994ef9d6b738322664d5fdd948f0fdeb46" },
"mason.nvim": { "branch": "main", "commit": "7f265cd6ae56cecdd0aa50c8c73fc593b0604801" },
"mini.icons": { "branch": "main", "commit": "397ed3807e96b59709ef3292f0a3e253d5c1dc0a" },
"neo-tree.nvim": { "branch": "main", "commit": "cea666ef965884414b1b71f6b39a537f9238bdb2" },
"neoconf.nvim": { "branch": "main", "commit": "907a1fe4e346aab2989af6848d7d697098506c5e" },
"none-ls.nvim": { "branch": "main", "commit": "db2a48b79cfcdab8baa5d3f37f21c78b6705c62e" },
"nui.nvim": { "branch": "main", "commit": "f535005e6ad1016383f24e39559833759453564e" },
"nvim-autopairs": { "branch": "master", "commit": "23320e75953ac82e559c610bec5a90d9c6dfa743" },
"nvim-dap": { "branch": "master", "commit": "14fe46ae16eb272629144a93f7738f5279665a4f" },
"nvim-dap-ui": { "branch": "master", "commit": "73a26abf4941aa27da59820fd6b028ebcdbcf932" },
"nvim-highlight-colors": { "branch": "main", "commit": "b42a5ccec7457b44e89f7ed3b3afb1b375bb2093" },
"nvim-lspconfig": { "branch": "master", "commit": "fa2662510d30b06168b6e2e6915518decde6bbac" },
"nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" },
"nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" },
"nvim-treesitter-textobjects": { "branch": "master", "commit": "89ebe73cd2836db80a22d9748999ace0241917a5" },
"nvim-ts-autotag": { "branch": "main", "commit": "a1d526af391f6aebb25a8795cbc05351ed3620b5" },
"nvim-ts-context-commentstring": { "branch": "main", "commit": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f" },
"nvim-ufo": { "branch": "main", "commit": "61463090a4f55f5d080236ea62f09d1cd8976ff3" },
"nvim-window-picker": { "branch": "main", "commit": "6382540b2ae5de6c793d4aa2e3fe6dbb518505ec" },
"plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" },
"promise-async": { "branch": "main", "commit": "38a4575da9497326badd3995e768b4ccf0bb153e" },
"resession.nvim": { "branch": "master", "commit": "cc819b0489938d03e4f3532a583354f0287c015b" },
"smart-splits.nvim": { "branch": "master", "commit": "ddb23c1a1cf1507bda487cda7f6e4690965ef9f5" },
"snacks.nvim": { "branch": "main", "commit": "5eac729fa290248acfe10916d92a5ed5e5c0f9ed" },
"todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" },
"toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" },
"vim-illuminate": { "branch": "master", "commit": "0d1e93684da00ab7c057410fecfc24f434698898" },
"which-key.nvim": { "branch": "main", "commit": "fcbf4eea17cb299c02557d576f0d568878e354a4" }
}
+76 -6
View File
@@ -2,10 +2,80 @@
-- We import this file in `lazy_setup.lua` before the `plugins/` folder. -- We import this file in `lazy_setup.lua` before the `plugins/` folder.
-- This guarantees that the specs are processed before any user plugins. -- This guarantees that the specs are processed before any user plugins.
---@type LazySpec --- @alias FrameworkModuleSpec { import: string }
return {
"AstroNvim/astrocommunity", --- @alias FrameworkModules table<string, FrameworkModuleSpec[]>
{ import = "astrocommunity.pack.lua" },
-- { import = "astrocommunity.completion.avante-nvim" }, -- Framework-specific community module configurations
-- import/override with your plugins folder --- @type FrameworkModules
local FRAMEWORK_COMMUNITY_MODULES = {
-- Base Lua pack - always included
lua = {
{ import = "astrocommunity.pack.lua" },
},
-- Vue.js framework modules
vue = {
{ import = "astrocommunity.pack.vue" },
},
} }
--- Retrieves the appropriate community modules based on the current framework environment
--- @return LazySpec[] List of community modules to import for the detected framework
local function get_framework_modules()
--- @type string|nil
local current_framework = os.getenv "FRAMEWORK"
--- @type LazySpec[]
local modules = {}
-- Always include base Lua pack
for _, module in ipairs(FRAMEWORK_COMMUNITY_MODULES.lua) do
table.insert(modules, module)
end
-- If framework is not set or empty string, use only base modules
if not current_framework or current_framework == "" then return modules end
-- Check if framework is valid (vue or python)
if current_framework ~= "vue" and current_framework ~= "python" then
error("Invalid framework: '" .. current_framework .. "'. Valid frameworks are: vue, python")
end
-- Add framework-specific modules if framework is valid
if FRAMEWORK_COMMUNITY_MODULES[current_framework] then
for _, module in ipairs(FRAMEWORK_COMMUNITY_MODULES[current_framework]) do
table.insert(modules, module)
end
end
return modules
end
--- Checks if third-party AI assistant is enabled and adds Avante-nvim if true
--- @return LazySpec|nil Avante-nvim module if AI is enabled, nil otherwise
local function get_ai_modules()
-- Check if third-party AI assistant is enabled
local ai_enabled = os.getenv "THIRD_PARTY_AI_ASSISTANT"
if ai_enabled and ai_enabled:lower() == "true" then return { import = "astrocommunity.completion.avante-nvim" } end
return nil
end
---@type LazySpec[]
local modules = {
-- Base AstroCommunity plugin
"AstroNvim/astrocommunity",
}
-- Add framework-specific modules
local framework_modules = get_framework_modules()
for _, module in ipairs(framework_modules) do
table.insert(modules, module)
end
-- Add AI modules if enabled
local ai_module = get_ai_modules()
if ai_module then
table.insert(modules, ai_module)
end
return modules
+1 -1
View File
@@ -1,7 +1,7 @@
require("lazy").setup({ require("lazy").setup({
{ {
"AstroNvim/AstroNvim", "AstroNvim/AstroNvim",
version = "5.3.4", -- Remove version tracking to elect for nightly AstroNvim version = "5.3.12", -- Remove version tracking to elect for nightly AstroNvim
import = "astronvim.plugins", import = "astronvim.plugins",
opts = { -- AstroNvim options must be set here with the `import` key opts = { -- AstroNvim options must be set here with the `import` key
mapleader = " ", -- This ensures the leader key must be configured before Lazy is set up mapleader = " ", -- This ensures the leader key must be configured before Lazy is set up
+2
View File
@@ -30,6 +30,8 @@ return {
-- disable lua_ls formatting capability if you want to use StyLua to format your lua code -- disable lua_ls formatting capability if you want to use StyLua to format your lua code
-- "lua_ls", -- "lua_ls",
"volar", "volar",
"vtsls",
"ts_ls",
}, },
timeout_ms = 7000, -- default format timeout timeout_ms = 7000, -- default format timeout
-- filter = function(client) -- fully override the default formatting function -- filter = function(client) -- fully override the default formatting function
+78 -8
View File
@@ -1,19 +1,89 @@
if true then return {} end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE -- Configuration module for avante.nvim plugin with DeepSeek API support
-- Returns configuration only if THIRD_PARTY_AI_ASSISTANT environment variable is set
-- Check for the required environment variable containing the API key
-- If the key is not set, returns an empty table and the plugin won't load
local ai_enabled = os.getenv "THIRD_PARTY_AI_ASSISTANT"
if not ai_enabled or ai_enabled:lower() ~= "true" then return {} end
-- Main plugin configuration object
---@type LazyPluginSpec[]
return { return {
{ -- further customize the options set by the community {
-- Plugin identifier in GitHub repository
"yetone/avante.nvim", "yetone/avante.nvim",
-- Plugin version for compatibility assurance
version = "0.0.27",
-- Plugin configuration options
-- Remove the type annotation if avante.Config is undefined
opts = { opts = {
provider = "deepseek", provider = "deepseek_safe",
auto_suggestions_provider = "deepseek",
providers = { behaviour = {
deepseek = { auto_approve_tool_permissions = true,
},
vendors = {
deepseek_safe = {
__inherited_from = "openai", __inherited_from = "openai",
api_key_name = "DEEPSEEK_API_KEY", api_key_name = "DEEPSEEK_API_KEY",
endpoint = "https://api.deepseek.com", endpoint = "https://api.deepseek.com",
model = "deepseek-coder", model = "deepseek-chat",
timeout = 120000,
max_tokens = 8192, max_tokens = 8192,
disable_tools = true, extra_request_body = {
temperature = 0,
max_tokens = 8192,
},
-- parse_curl_args = function(opts, code_opts)
-- local log_file = io.open("/tmp/avante_debug.log", "a")
--
-- -- Helper function to extract text from content
-- local function get_content_text(content)
-- if type(content) == "string" then
-- return content
-- elseif type(content) == "table" then
-- -- Content can be array of {type="text", text="..."}
-- if content.text then
-- return content.text
-- elseif content[1] and content[1].text then
-- return content[1].text
-- end
-- return vim.inspect(content) -- fallback
-- end
-- return ""
-- end
--
-- if log_file and code_opts.messages then
-- log_file:write "\n=== NEW REQUEST ===\n"
-- log_file:write(string.format("Total messages: %d\n", #code_opts.messages))
--
-- -- Check for duplicates
-- if #code_opts.messages >= 2 then
-- local last = code_opts.messages[#code_opts.messages]
-- local prev = code_opts.messages[#code_opts.messages - 1]
--
-- local last_text = get_content_text(last.content)
-- local prev_text = get_content_text(prev.content)
--
-- log_file:write(string.format("\nLast text: %s\n", last_text))
-- log_file:write(string.format("Prev text: %s\n", prev_text))
--
-- if last_text == prev_text and last_text ~= "" then
-- log_file:write "\n!!! DUPLICATE DETECTED !!!\n"
-- log_file:close()
-- vim.notify("Duplicate message detected! Aborting.", vim.log.levels.ERROR)
-- return nil
-- end
-- end
--
-- log_file:close()
-- end
--
-- local openai = require("avante.providers").openai
-- return openai.parse_curl_args(opts, code_opts)
-- end,
}, },
}, },
}, },
-1
View File
@@ -1 +0,0 @@
init.lua
-16
View File
@@ -1,16 +0,0 @@
-- config.lua
local config = {
-- lspconfig
"eslint-lsp",
"stylelint-lsp",
"tailwindcss-language-server",
"typescript-language-server",
-- "vue-language-server",
{ "vue-language-server", version = "1.8.27" },
-- null_ls
"stylelint",
"prettier",
}
return config
-15
View File
@@ -1,15 +0,0 @@
local vue = require "plugins.mason.vue"
-- Customize Mason
---@type LazySpec
return {
-- use mason-tool-installer for automatically installing Mason packages
{
"WhoIsSethDaniel/mason-tool-installer.nvim",
-- overrides `require("mason-tool-installer").setup(...)`
opts = {
-- Make sure to use the names found in `:Mason`
ensure_installed = vue,
},
},
}
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# Path to the branch_time_calculator.py script
CALCULATOR_PATH="$HOME/.config/nvim/lua/plugins/pendulum/branch_time_calculator.py"
# Check if the calculator script exists
if [ ! -f "$CALCULATOR_PATH" ]; then
echo "Error: The branch_time_calculator.py script was not found at $CALCULATOR_PATH."
echo "Please ensure the 'pendulum' plugin is installed in your Neovim configuration."
exit 1
fi
# Execute the calculator script
python3 "$CALCULATOR_PATH" "$@"
@@ -0,0 +1,182 @@
import csv
import datetime
import os
import subprocess
import argparse
from typing import Optional, Dict, List
class BranchTimeCalculator:
"""
A class to calculate time spent on a Git branch with exact project matching.
Handles lowercase 'true' for active status and flexible CSV parsing.
"""
def __init__(self, csv_file: Optional[str] = None, target_branch: Optional[str] = None, debug: bool = False):
"""
Initialize the calculator with optional CSV file, target branch and debug mode.
Args:
csv_file (Optional[str]): Path to CSV log file. Defaults to ~/pendulum-log.csv.
target_branch (Optional[str]): Name of the target branch. Defaults to current branch.
debug (bool): If True, prints debug information. Defaults to False.
"""
self.csv_file = csv_file or os.path.expanduser("~/pendulum-log.csv")
self.target_branch = target_branch
self.debug = debug
self.current_project = self._get_project_name()
def _get_project_name(self) -> str:
"""
Get the project name from Git config or fall back to directory name.
Returns:
str: The project name.
"""
try:
return subprocess.check_output(
["git", "config", "--get", "remote.origin.url"],
stderr=subprocess.DEVNULL,
text=True
).strip().split('/')[-1].replace('.git', '')
except subprocess.CalledProcessError:
return os.path.basename(os.path.dirname(os.path.abspath(__file__)))
def _get_current_branch(self) -> Optional[str]:
"""
Get the current Git branch name.
Returns:
Optional[str]: The branch name or None if not in a Git repo.
"""
try:
return subprocess.check_output(
["git", "branch", "--show-current"],
stderr=subprocess.DEVNULL,
text=True
).strip()
except subprocess.CalledProcessError:
print("Error: Not a Git repository or branch not found.")
return None
def _parse_log_entry(self, row: List[str]) -> Dict[str, str]:
"""
Parse a CSV row into a log entry dictionary.
Args:
row (List[str]): A row from the CSV log file.
Returns:
Dict[str, str]: A dictionary representing the log entry.
"""
return {
'active': row[0].lower().strip(),
'branch': row[1].strip(),
'directory': row[2].strip(),
'file': row[3].strip(),
'filetype': row[4].strip(),
'project': row[5].strip(),
'time': row[6].strip()
}
def _calculate_time_deltas(self, log_entries: List[Dict[str, str]]) -> Dict[str, datetime.timedelta]:
"""
Calculate total and active time from log entries.
Args:
log_entries (List[Dict[str, str]]): List of parsed log entries.
Returns:
Dict[str, datetime.timedelta]: A dictionary with 'total_time' and 'active_time'.
"""
total_time = datetime.timedelta()
active_time = datetime.timedelta()
prev_time = None
for entry in log_entries:
try:
current_time = datetime.datetime.strptime(entry['time'], '%Y-%m-%d %H:%M:%S')
except ValueError as e:
print(f"[ERROR] Time parse failed: {entry['time']}. Error: {e}")
continue
if prev_time is not None:
time_diff = current_time - prev_time
total_time += time_diff
if entry['active'] == 'true':
active_time += time_diff
prev_time = current_time
return {'total_time': total_time, 'active_time': active_time}
def calculate(self) -> Optional[Dict[str, any]]:
"""
Calculate time spent on the target branch.
Returns:
Optional[Dict[str, any]]: A dictionary with branch, project, total_time, active_time, and active_percentage.
Returns None if calculation fails.
"""
if self.target_branch is None:
self.target_branch = self._get_current_branch()
if self.target_branch is None:
return None
log_entries = []
try:
with open(self.csv_file, mode='r') as file:
for line in file:
row = list(csv.reader([line.strip()], delimiter=',', quotechar='"'))[0]
if len(row) != 7:
if self.debug:
print(f"[DEBUG] Skipping malformed line: {line}")
continue
log_entry = self._parse_log_entry(row)
if log_entry['branch'] == self.target_branch and log_entry['project'] == self.current_project:
log_entries.append(log_entry)
except FileNotFoundError:
print(f"Error: Log file not found at {self.csv_file}")
return None
time_deltas = self._calculate_time_deltas(log_entries)
total_seconds = time_deltas['total_time'].total_seconds()
active_percentage = (time_deltas['active_time'].total_seconds() / total_seconds) * 100 if total_seconds > 0 else 0
if self.debug:
print(f"\nTime spent on branch '{self.target_branch}' in project '{self.current_project}':")
print(f"- Total time: {time_deltas['total_time']}")
print(f"- Active time: {time_deltas['active_time']}")
print(f"- Active percentage: {active_percentage:.2f}%")
else:
print(f"In project '{self.current_project}' on branch '{self.target_branch}' you spent actively working: {time_deltas['active_time']}")
return {
'branch': self.target_branch,
'project': self.current_project,
'total_time': time_deltas['total_time'],
'active_time': time_deltas['active_time'],
'active_percentage': active_percentage
}
def main():
"""Main function to parse arguments and run the calculator."""
parser = argparse.ArgumentParser(description='Calculate branch activity time.')
parser.add_argument('--csv-file', type=str, help='Path to CSV log (default: ~/pendulum-log.csv)')
parser.add_argument('--branch', type=str, help='Branch name (default: current)')
parser.add_argument('--debug', action='store_true', help='Enable debug output')
args = parser.parse_args()
calculator = BranchTimeCalculator(args.csv_file, args.branch, args.debug)
result = calculator.calculate()
if not result:
print("\nCalculation failed - check debug output above.")
if __name__ == '__main__':
main()
+11
View File
@@ -0,0 +1,11 @@
---@type LazySpec
return {
"ptdewey/pendulum-nvim",
version = "1.1.0",
config = function()
require("pendulum").setup {
time_zone = "Europe/Moscow",
gen_reports = false,
}
end,
}
-5
View File
@@ -1,5 +0,0 @@
if true then return end -- WARN: REMOVE THIS LINE TO ACTIVATE THIS FILE
-- This will run last in the setup process.
-- This is just pure lua so anything that doesn't
-- fit in the normal config locations above can go here
+154
View File
@@ -0,0 +1,154 @@
--- Mason package installation utilities for Neovim.
--- This module provides functions for installing Mason packages based on framework environment.
--- @alias FrameworkName "python"|"vue"|string
--- @class FrameworkTools
--- @field python string[] Python development tools and LSP servers including formatters, linters, and type checkers
--- @field vue string[] Vue.js development tools and LSP servers including JavaScript/TypeScript tools and CSS utilities
--- Framework-specific tool configurations
--- Maps framework names to their respective tool lists
--- @type FrameworkTools
local FRAMEWORK_TOOLS = {
python = {
"black",
"python-lsp-server",
"mypy",
"pylint",
"flake8",
"pylama",
"bandit",
"pydocstyle",
"pyproject-flake8",
"pyproject-fmt",
"reorder-python-imports",
},
vue = {
"eslint-lsp",
"stylelint-lsp",
"tailwindcss-language-server",
"typescript-language-server",
"stylelint",
"prettier",
},
}
--- Retrieves the appropriate tool set based on the current framework environment.
--- This function checks the FRAMEWORK environment variable and returns the corresponding
--- tool list from FRAMEWORK_TOOLS. If no framework is set or the framework is not recognized,
--- returns an empty table.
--- @return string[] tools List of tools to install for the detected framework, or empty table if no framework is set
local function get_framework_tools()
local current_framework = os.getenv "FRAMEWORK"
if current_framework then
local tools = FRAMEWORK_TOOLS[current_framework]
return tools or {}
else
return {}
end
end
--- Validates if a package name is safe to install.
--- This function performs basic security validation to prevent command injection
--- and ensures package names follow expected patterns.
--- @param package_name string The package name to validate
--- @return boolean is_valid True if the package name is valid, false otherwise
local function is_valid_package_name(package_name)
-- Basic validation: package names should only contain alphanumeric characters, hyphens, and dots
-- This prevents command injection attacks
if type(package_name) ~= "string" or package_name == "" then return false end
-- Additional security: check for potentially dangerous patterns
local dangerous_patterns = {
"%.%.%/", -- Path traversal
"%;", -- Command separator
"%|", -- Pipe
"%&", -- Background process
"%`", -- Command substitution
"%$", -- Variable expansion
"%!", -- History expansion
}
for _, pattern in ipairs(dangerous_patterns) do
if string.match(package_name, pattern) then return false end
end
-- Check for valid characters: alphanumeric, hyphen, dot, underscore
local valid_pattern = "^[%w%-%.%_]+$"
return string.match(package_name, valid_pattern) ~= nil
end
--- Checks if Mason is available and ready for package installation.
--- @return boolean is_available True if Mason is available, false otherwise
local function is_mason_available()
local mason_ok, _ = pcall(require, "mason")
return mason_ok
end
--- Installs Mason packages based on the current framework environment.
--- This function retrieves the appropriate tool set and installs them one by one
--- to handle individual failures gracefully. Each package installation is wrapped
--- in a protected call to prevent one failure from stopping the entire process.
--- @return nil
function InstallMyMasonPackages()
-- Check if Mason is available first
if not is_mason_available() then
vim.notify("Mason is not available. Please install Mason first.", vim.log.levels.ERROR)
return
end
local packages = get_framework_tools()
if #packages > 0 then
local installed_count = 0
local failed_count = 0
-- Install packages one by one to handle individual failures
for _, package in ipairs(packages) do
-- Validate package name for security
if not is_valid_package_name(package) then
vim.notify("Skipping invalid package name: " .. package, vim.log.levels.WARN)
failed_count = failed_count + 1
else
local success, result = pcall(function() vim.cmd("MasonInstall " .. package) end)
if success then
installed_count = installed_count + 1
vim.notify("Successfully installed: " .. package, vim.log.levels.INFO)
else
failed_count = failed_count + 1
vim.notify("Failed to install " .. package .. ": " .. tostring(result), vim.log.levels.WARN)
end
end
end
-- Provide summary
if failed_count == 0 then
vim.notify(
"Framework-specific packages installation completed successfully. Installed: " .. installed_count .. " packages",
vim.log.levels.INFO
)
else
vim.notify(
"Framework-specific packages installation completed with "
.. failed_count
.. " failures. Successfully installed: "
.. installed_count
.. " packages",
vim.log.levels.WARN
)
end
else
vim.notify("No framework detected or no packages to install", vim.log.levels.INFO)
end
end
-- Module exports
return {
FRAMEWORK_TOOLS = FRAMEWORK_TOOLS,
get_framework_tools = get_framework_tools,
InstallMyMasonPackages = InstallMyMasonPackages,
}
+23
View File
@@ -0,0 +1,23 @@
--- @meta
--- Framework-specific tool configurations and installation utilities for Neovim.
--- This module provides automatic installation of language servers and tools
--- based on the current development framework environment.
--- It reads the FRAMEWORK environment variable to determine which tools to install.
-- Import Mason utilities from separate module
local mason = require "polish.framework_mason_packages"
-- Create user command for Mason installation
vim.api.nvim_create_user_command(
"MasonInstallForFramework", -- Command name
mason.InstallMyMasonPackages, -- Function to call
{ nargs = 0 } -- Command takes no arguments
)
-- Module exports
return {
FRAMEWORK_TOOLS = mason.FRAMEWORK_TOOLS,
get_framework_tools = mason.get_framework_tools,
InstallMyMasonPackages = mason.InstallMyMasonPackages,
}