最近从 Powershell 转到 Nushell,参考 nu_scripts 中现有的代码,写了个满足自己日常使用习惯的管理 Python 虚拟环境的脚本。(Linux 还是习惯使用 zsh + virtualenvwrapper)
图片.png
# Developed using nushell v0.111.0
# NOTE: Manually SET path name to PATH on windows to avoid weird bugs!!!
const NU_VENV_VERSION = "1.0.0"
const PATH_NAME = "PATH"
const INFO_STYLE = $'(ansi green)'
const WARN_STYLE = $'(ansi yellow)'
const ERR_STYLE = $'(ansi red)'
# I mainly use nushell on windows.
let is_windows = ($nu.os-info.name == "windows")
let path_sep = (if $is_windows { '\' } else { '/' })
let venv_home = if $is_windows { ($nu.home-dir | path join "Pyvenv") } else { $nu.home-dir | path join ".virtualenvs" }
# Make a new virtualenv using pyvenv
#
@example "mkvenv httpie" {mkvenv httpie} --result r#'
# $HOME/Pyvenv is a soft link here.
Actual environment location may have moved due to redirects, links or junctions.
Requested location: "C:\Users\<YourName>\Pyvenv\http\Scripts\python.exe"
Actual location: "X:\<RealPath>\Pyvenv\http\Scripts\python.exe'#
export def mkvenv [
name: string # venv name
] {
let new_venv_path = ($venv_home | path join $name)
if ($new_venv_path | path exists) {
print $"($ERR_STYLE)venv ($name) exists, doing nothing"
return
}
python -m venv $new_venv_path
}
# List all virtualenvs
#
@example "lsvenv" {lsvenv} --result "
venv1
venv2
venv3"
export def lsvenv [] {
ls $venv_home | where type == dir | each {|d| $d.name | path basename}
}
# Remove venv by name
#
@example "rmvenv httpie" {rmvenv httpie} --result "rm venv dir on venv_home"
export def rmvenv [
name: string # venv name
] {
let venv_path = ($venv_home | path join $name)
let exists = ($venv_path | path exists)
if (not $exists) {
print $'($WARN_STYLE)($venv_path) not exists, nothing to do'
return
}
let current_venv = ($env.VIRTUAL_ENV? | default null)
if ($venv_path == $current_venv) {
print $"($ERR_STYLE)($venv_path) is activated, deactivate it before deletion"
return
}
rm -r $venv_path
}
def is-string [x] {
($x | describe) == 'string'
}
def has-env [name: string] {
$name in ($env)
}
# Activate venv
# If no name is specified, all venvs will be printed.
#
@example "workon httpie" {workon httpie} --result "prompt will display activated venv"
export def --env workon [
name?: string # venv name
] {
if ($name | is-empty) {
return (lsvenv)
}
mut virtual_env = $env.VIRTUAL_ENV? | default null
if $virtual_env != null {
deactivate
}
$virtual_env = ($venv_home | path join $name)
if (not ($virtual_env | path exists)) {
print $"($WARN_STYLE)venv ($name) not exists, doing nothing"
return
}
let bin = (if $is_windows { [$virtual_env, "Scripts"] | path join } else {[$virtual_env, "bin"] | path join})
let virtual_prompt = ""
let old_path = (
if ($is_windows) and (has-env "Path") {
$env.Path
} else {
$env.PATH
}
| if (is-string $in) {
# if Path/PATH is a string, make it a list
$in | split row $path_sep | path expand
} else {
$in
}
)
let venv_path = ([$virtual_env $bin] | path join)
# let new_path = ($old_path | prepend $venv_path | str join $path_sep)
let new_path = ($old_path | prepend $venv_path)
# Creating the new prompt for the session
let virtual_prompt = if ($virtual_prompt == '') {
$'(char lbracket)py:($name)(char rbracket) '
} else {
'[py:' + $virtual_prompt + '] '
}
let new_env = {
OLD_PATH: $old_path
$PATH_NAME: $new_path
VIRTUAL_ENV: $virtual_env
VIRTUAL_PROMPT: $virtual_prompt
# OLD_PROMPT_COMMAND: $old_prompt_command
# PROMPT_COMMAND : $new_prompt
# NU_LIB_DIRS : $new_lib_dirs
}
# Activate the environment variables
load-env $new_env
}
export def --env deactivate [] {
if ($env.VIRTUAL_ENV? | default null) == null {
print $"($WARN_STYLE)No venv found, exiting"
return
}
$env.PATH = $env.OLD_PATH
hide-env OLD_PATH
hide-env VIRTUAL_ENV
hide-env VIRTUAL_PROMPT
}
export alias pydoc = python -m pydoc
export alias pip = python -m pip
|