├── LICENSE ├── README.md └── nvim-python-doctor.sh /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Tommy Allen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :warning: **NOTICE: This has been ported to `:CheckHealth` command that ships with Neovim and it is more informative!** 2 | 3 | If you are using a distribution package and can't get the latest version of Neovim yet, you can install the following plugin to get the `:CheckHealth` command: https://github.com/tweekmonster/nvim-checkhealth 4 | 5 | # ~~Neovim Python Doctor~~ 6 | 7 | ~~Display diagnostic information about your Python installations and how they are 8 | viewed by Neovim.~~ 9 | 10 | ## Usage 11 | 12 | **Note**: `nvim` will be executed using your current configurations 13 | 14 | Download and run `nvim-python-doctor.sh` 15 | 16 | or run via curl: 17 | 18 | ```shell 19 | curl -fsSL https://git.io/vwlfI | bash 20 | ``` 21 | 22 | If you decide to use the curl method, at least confirm that the shortened URL 23 | points to the correct script beforehand: 24 | https://raw.githubusercontent.com/tweekmonster/nvim-python-doctor/master/nvim-python-doctor.sh 25 | -------------------------------------------------------------------------------- /nvim-python-doctor.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | need_py2=0 3 | need_py3=0 4 | upgrade_py32=0 5 | has_pyenv=0 6 | python_versions=() 7 | messages=() 8 | 9 | tempfiles=$(mktemp -t "nvim_doctor.XXXXXXXX") 10 | cleanup_temp() { 11 | xargs rm -f < "$tempfiles" 12 | rm -f "$tempfiles" 13 | 14 | if [[ ${#messages[@]} -gt 0 ]]; then 15 | echo 16 | section "## Messages or Suggestions" 17 | echo 18 | 19 | for msg in "${messages[@]}"; do 20 | echo "- $msg" 21 | done 22 | fi 23 | } 24 | 25 | mktempfile() { 26 | mktemp -t "nvim_doctor.XXXXXXXX" | tee -a "$tempfiles" 27 | } 28 | 29 | trap cleanup_temp EXIT 30 | 31 | success() { 32 | if [ -t 1 ]; then 33 | echo -e "\e[32m$@\e[m" 34 | else 35 | echo "$@" 36 | fi 37 | } 38 | 39 | info() { 40 | if [ -t 1 ]; then 41 | echo -e "\e[36m$@\e[m" 42 | else 43 | echo "$@" 44 | fi 45 | } 46 | 47 | warn() { 48 | if [ -t 1 ]; then 49 | echo -e "\e[33m$@\e[m" 50 | else 51 | echo "$@" 52 | fi 53 | } 54 | 55 | err() { 56 | if [ -t 1 ]; then 57 | echo -e "\e[31m$@\e[m" 58 | else 59 | echo "$@" 60 | fi 61 | } 62 | 63 | section() { 64 | if [ -t 1 ]; then 65 | echo -e "\e[1;37m$@\e[m" 66 | else 67 | echo "$@" 68 | fi 69 | } 70 | 71 | echo "Include the output below this line in your Github issues." 1>&2 72 | echo 1>&2 73 | echo 1>&2 74 | 75 | section "## Neovim Python Diagnostic" 76 | echo 77 | 78 | nvim=$(which nvim) 79 | if [[ ! -e "$nvim" ]]; then 80 | err "- nvim not found. Maybe that's your problem?" 81 | exit 1 82 | fi 83 | 84 | echo -n "- Neovim Version: " 85 | info "$($nvim --version | head -n 1)" 86 | 87 | python_client_latest=$(curl -fsS https://pypi.python.org/pypi/neovim/json | awk -F\" '/^\s+"version":/ { print $4 }') 88 | 89 | 90 | WHICH_CMD="which" 91 | if type pyenv >/dev/null 2>&1; then 92 | eval "$(pyenv init -)" 93 | has_pyenv=1 94 | WHICH_CMD="pyenv which" 95 | echo "- \`pyenv\` is available" 96 | old_IFS="$IFS" 97 | IFS=$'\n' 98 | for v in $(pyenv version); do 99 | echo " - $v" 100 | done 101 | IFS="$old_IFS" 102 | fi 103 | 104 | if [[ -n "$VIRTUAL_ENV" ]]; then 105 | venv_python="${VIRTUAL_ENV}/bin/python" 106 | echo "- \`virtualenv\` active: $(${VIRTUAL_ENV}/bin/python -V 2>&1)" 107 | echo " - Path: $VIRTUAL_ENV" 108 | fi 109 | 110 | 111 | test_nvim() { 112 | exe="$1" 113 | echo 114 | section "### '$exe' info from $nvim" 115 | echo 116 | nvim_var="${exe}_host_prog" 117 | tempfile="$(mktempfile)" 118 | 119 | $nvim --headless \ 120 | +"redir! > $tempfile" \ 121 | +"silent echo get(g:, '$nvim_var', '')" \ 122 | +"redir END" \ 123 | +"qa!" 2> /dev/null 124 | python_path=$(grep -e . $tempfile) 125 | if [[ -z "$python_path" ]]; then 126 | warn "WARN: 'g:${nvim_var}' is not set." 127 | python_path=$($WHICH_CMD $exe 2>&1) 128 | if [[ $? -ne 0 || -z "$python_path" ]]; then 129 | messages+=("ERR: \`$exe\` could not be found in \$PATH. If it does exist, you will need to use \`g:$nvim_var\` to point to it.") 130 | err "\`$WHICH_CMD $exe\` returned nothing." 131 | return 1 132 | else 133 | warn "WARN: Fallback to '$python_path'" 134 | fi 135 | else 136 | echo "**Config**: \`let g:$nvim_var = '$python_path'\`" 137 | fi 138 | 139 | local is_pyenv=0 140 | if [[ $has_pyenv -eq 1 && -s "$PYENV_ROOT" ]]; then 141 | if [[ $python_path == "$PYENV_ROOT/"* ]]; then 142 | is_pyenv=1 143 | else 144 | messages+=("WARN: You have \`pyenv\`, but \`$exe\` is not pointing to a pyenv installation.") 145 | fi 146 | fi 147 | 148 | python_version="$($python_path -V 2>&1 | awk -F ' ' '{ print $2 }')" 149 | if [[ "$exe" == "python3" && $python_version =~ ^2\. ]]; then 150 | messages+=("ERR: \`python3\` version should be Python 3.x, but is version \`$python_version\`.") 151 | elif [[ "$exe" == "python" && $python_version =~ ^3\. ]]; then 152 | messages+=("WARN: \`python\` version should be Python 2.x, but is version \`$python_version\`.") 153 | fi 154 | 155 | python_versions+=("$python_version") 156 | if [[ $upgrade_py32 -eq 0 && $python_version =~ ^3\.(0|1|2) ]]; then 157 | upgrade_py32=1 158 | messages+=("FIX: Python 3.3 or greater is recommended. The current version Neovim is using: \`$python_version\`.") 159 | fi 160 | echo "**Python Version**: \`$python_version\`" 161 | 162 | echo -n "**Neovim Package Version**: " 163 | nvim_package=$($python_path -m pip list 2>&1) 164 | local no_pip=0 165 | if [[ "$nvim_package" =~ "No module named pip" ]]; then 166 | no_pip=1 167 | fi 168 | 169 | nvim_package=$(echo "$nvim_package" | grep -E '^neovim\s' | sed -e 's/.\+(\(.\+\))/\1/g') 170 | if [[ -z "$nvim_package" ]]; then 171 | if [[ $no_pip -eq 1 ]]; then 172 | messages+=("ERR: pip is not installed for \`$exe\`. It is assumed that the neovim package is not installed.") 173 | else 174 | if [[ $is_pyenv -eq 1 ]]; then 175 | messages+=("FIX: The neovim package is not installed in the pyenv installation for \`$exe\`.") 176 | else 177 | messages+=("FIX: Install the neovim package with: \`pip${python_version%%.*} install --user neovim\`.") 178 | fi 179 | fi 180 | err "not installed" 181 | else 182 | echo -n "\`$nvim_package\`" 183 | if [[ "$nvim_package" != "$python_client_latest" ]]; then 184 | if [[ $is_pyenv -eq 1 ]]; then 185 | messages+=("FIX: The pyenv package for neovim is outdated in the pyenv installation for \`$exe\`.") 186 | else 187 | messages+=("FIX: Upgrade the neovim package with: \`pip${python_version%%.*} install -U --user neovim\`.") 188 | fi 189 | warn " (latest: \`$python_client_latest\`)" 190 | else 191 | echo 192 | fi 193 | fi 194 | } 195 | 196 | 197 | check_remote_plugins() { 198 | tempfile="$(mktempfile)" 199 | rtp_tempfile="$(mktempfile)" 200 | $nvim --headless \ 201 | +"redir! > $tempfile" \ 202 | +"silent echo \$MYVIMRC" \ 203 | +"redir END" \ 204 | +"redir! > $rtp_tempfile" \ 205 | +"silent echo join(map(split(&rtp, ','), 'resolve(v:val)'), \"\\n\")" \ 206 | +"redir END" \ 207 | +"qa!" 2> /dev/null 208 | 209 | init_file=$(grep -e . $tempfile) 210 | init_base=${init_file##*/} 211 | init_dir=${init_file%%/$init_base} 212 | manifest_file="$init_dir/.${init_base}-rplugin~" 213 | 214 | echo "**Manifest File**: \`${manifest_file:-MISSING}\`" 215 | 216 | rplugins=() 217 | unregistered=() 218 | 219 | for rtp in $(<$rtp_tempfile); do 220 | rtp="${rtp%%/}" 221 | check="" 222 | if [[ -d "$rtp/rplugin/python" ]]; then 223 | (( need_py2++ )) 224 | check="$rtp/rplugin/python" 225 | elif [[ -d "$rtp/rplugin/python3" ]]; then 226 | (( need_py3++ )) 227 | check="$rtp/rplugin/python3" 228 | fi 229 | 230 | if [[ -n "$check" ]]; then 231 | for p in $check/{*.py,*/__init__.py}; do 232 | if [[ -f "$p" ]]; then 233 | if grep -E '^(from|import)\s+neovim' "$p" >/dev/null 2>&1; then 234 | p="${p%%/__init__.py}" 235 | rplugins+=("$p") 236 | fi 237 | fi 238 | done 239 | fi 240 | done 241 | 242 | local need_update=0 243 | 244 | for rplugin in ${rplugins[@]}; do 245 | echo "**Plugin**: $rplugin" 246 | echo -n " - Registered: " 247 | if grep -F "'$rplugin'" $manifest_file >/dev/null 2>&1; then 248 | success "Yes" 249 | else 250 | need_update=1 251 | err "No" 252 | fi 253 | done 254 | 255 | if [[ $need_update -eq 1 ]]; then 256 | err '**Manifest is not up to date**' 257 | messages+=('ERR: You need to run `:UpdateRemotePlugins` in Neovim to enable plugins.') 258 | else 259 | info '**Manifest is up to date**' 260 | fi 261 | } 262 | 263 | 264 | echo 265 | section "## Remote plugins" 266 | echo 267 | 268 | check_remote_plugins 269 | 270 | test_nvim "python" 271 | test_nvim "python3" 272 | 273 | IFS=$'\n' uniq_versions=($(sort <<<"${python_versions[*]}" | uniq)) 274 | if [[ "${#python_versions[@]}" -ne "${#uniq_versions[@]}" ]]; then 275 | messages+=("WARN: \`python\` and \`python3\` are using the same version: \`${uniq_versions[@]}\`.") 276 | fi 277 | 278 | echo 279 | section "## Python versions visible in the current shell" 280 | echo 281 | 282 | tests=("python" "python3") 283 | for py in ${tests[@]}; do 284 | cmd=$(eval $WHICH_CMD $py 2>/dev/null) 285 | if [[ $? -eq 0 && -e "$cmd" ]]; then 286 | echo "- **${py}** version: \`$($cmd -V 2>&1 | head -n 1)\`" 287 | echo " - **path**: \`$cmd\`" 288 | nvim_package=$($py -m pip list 2>/dev/null | grep -E '^neovim\s') 289 | if [[ -z "$nvim_package" ]]; then 290 | nvim_package="Not installed" 291 | fi 292 | echo " - **neovim** version: \`$nvim_package\`" 293 | else 294 | echo "- **${py}**: $cmd" 295 | fi 296 | done 297 | --------------------------------------------------------------------------------