Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions lua/swenv/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ local M = {}
local Path = require('plenary.path')
local scan_dir = require('plenary.scandir').scan_dir
local best_match = require('swenv.match').best_match
local read_venv_name = require('swenv.project').read_venv_name
local get_project_venv = require('swenv.project').get_project_venv
local get_local_venv = require('swenv.project').get_local_venv

local settings = require('swenv.config').settings

Expand Down Expand Up @@ -47,7 +48,16 @@ local has_high_priority_in_path = function(first, second)
if second == nil or second == vim.NIL then
return true
end
local prior_first = string.find(ORIGINAL_PATH, first)
local prior_second = string.find(ORIGINAL_PATH, second)

if prior_first == nil or prior_first == vim.NIL then
return false
end

if prior_second == nil or prior_second == vim.NIL then
return true
end
return string.find(ORIGINAL_PATH, first) < string.find(ORIGINAL_PATH, second)
end

Expand All @@ -71,7 +81,6 @@ M.init = function()
source = 'conda',
}
end

if venv then
current_venv = venv
end
Expand Down Expand Up @@ -193,15 +202,23 @@ M.auto_venv = function()

local project_dir, _ = project_nvim.get_project_root()
if project_dir then -- project_nvim.get_project_root might not always return a project path
local project_venv_name = read_venv_name(project_dir)
if not project_venv_name then
local venv_name = get_project_venv(project_dir)
if not venv_name then

return
end
local closest_match = best_match(venvs, project_venv_name)
if not closest_match then
if venv_name == '/.venv/' then
local venv = get_local_venv(project_dir .. venv_name)
if venv then
table.insert(venvs, venv)
set_venv(venv)
end
return
end
set_venv(closest_match)
local closest_match = best_match(venvs, venv_name)
if closest_match then
set_venv(closest_match)
end
end
end

Expand Down
11 changes: 11 additions & 0 deletions lua/swenv/match.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ end

-- Function to find the best match based on Levenshtein distance
M.best_match = function(items, query)
-- filter by contains query-string in elements
local filtered_items = {}
for _, item in ipairs(items) do
if string.find(item.name, query) then
table.insert(filtered_items, item)
end
end
if #filtered_items > 0 then
items = filtered_items
end

local min_distance = math.huge -- Initialize minimum distance as infinity
local match = nil -- Initialize match as nil to handle case if no match found
for _, item in ipairs(items) do -- Iterate over items
Expand Down
32 changes: 30 additions & 2 deletions lua/swenv/project.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
local M = {}
-- local Path = require('plenary.path')

local function isdir(dir_path)
return vim.fn.isdirectory(dir_path) ~= 0
end

-- get_local_venv from ./.venv dir
M.get_local_venv = function(venv_path)
local venv_cfg = io.open(venv_path .. '/pyvenv.cfg', 'r')
if not venv_cfg then
return nil
end

local configText = venv_cfg:read('*a') -- *a or *all reads the whole file
local pattern = "prompt%s*=%s*([%w_%p]+)" --"prompt%s*=%s*([%w_]+)"
local venv_name = configText:match(pattern)

local venv = {
name = venv_name,
path = venv_path,
source = 'local',
}
return venv
end

-- Get the name from a `.venv` file in the project root directory.
M.read_venv_name = function(project_dir)
local file = io.open(project_dir .. '/.venv', 'r') -- r read mode
M.get_project_venv = function(project_dir)
local venv_path = project_dir .. '/.venv'
local file = io.open(venv_path, 'r') -- r read mode
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe move this below the if-statement since it's not needed if the body is executed

if isdir(venv_path) then
return '/.venv/' -- sign of local venv
end
if not file then
return nil
end
Expand Down