Merge pull request #92 from justinbarclay/master

Make programming environment version parsing asynchronous
This commit is contained in:
Vincent Zhang 2019-01-13 16:42:25 +08:00 committed by GitHub
commit 539e361d9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 196 additions and 36 deletions

View file

@ -77,6 +77,7 @@
(require 'eldoc-eval) (require 'eldoc-eval)
(require 'shrink-path) (require 'shrink-path)
(require 'subr-x) (require 'subr-x)
(require 'doom-version-parser)
(when (>= emacs-major-version 26) (when (>= emacs-major-version 26)
(require 'project)) (require 'project))
@ -540,7 +541,10 @@ If DEFAULT is non-nil, set the default mode-line for all buffers."
;; Show version string for multi-version managers like rvm, rbenv, pyenv, etc. ;; Show version string for multi-version managers like rvm, rbenv, pyenv, etc.
(defvar-local doom-modeline-env-version nil) (defvar-local doom-modeline-env-version nil)
(defvar-local doom-modeline-env-command nil)
(defvar-local doom-modeline-env-command nil "A program that we're looking to extract version information from. Ex: \"ruby\"")
(defvar-local doom-modeline-env-command-args nil "A list of arguments to pass to `doom-modeline-env-command` to extract the version from. Ex: '(\"--version\") ")
(defvar-local doom-modeline-env-parser nil "A function that returns version number from a programs --version (or similar) command. Ex: 'doom-version-parser--ruby")
(add-hook 'find-file-hook #'doom-modeline-update-env) (add-hook 'find-file-hook #'doom-modeline-update-env)
(with-no-warnings (with-no-warnings
(if (boundp 'after-focus-change-function) (if (boundp 'after-focus-change-function)
@ -551,13 +555,16 @@ If DEFAULT is non-nil, set the default mode-line for all buffers."
(add-hook 'focus-in-hook #'doom-modeline-update-env))) (add-hook 'focus-in-hook #'doom-modeline-update-env)))
(defun doom-modeline-update-env () (defun doom-modeline-update-env ()
"Update environment info on mode-line." "Update environment info on mode-line."
(when (and doom-modeline-version doom-modeline-env-command) (when (and doom-modeline-version
(let ((default-directory (doom-modeline-project-root)) doom-modeline-env-command
(s (shell-command-to-string doom-modeline-env-command))) (executable-find doom-modeline-env-command)
(setq doom-modeline-env-version (if (string-match "[ \t\n\r]+\\'" s) doom-modeline-env-command-args
(replace-match "" t t s) doom-modeline-env-parser)
s))))) (let ((default-directory (doom-modeline-project-root)))
(doom-version-parser--get doom-modeline-env-command
doom-modeline-env-command-args
(lambda (prog-version)
(setq doom-modeline-env-version (funcall doom-modeline-env-parser prog-version)))))))
;; ;;
;; Modeline helpers ;; Modeline helpers
@ -2088,45 +2095,41 @@ mouse-1: Toggle Debug on Quit"
;; Versions, support Python, Ruby, Perl and Golang, etc. ;; Versions, support Python, Ruby, Perl and Golang, etc.
(add-hook 'python-mode-hook (add-hook 'python-mode-hook
(lambda () (lambda ()
(cond ((and (fboundp 'pipenv-project-p) (pipenv-project-p) (executable-find "pipenv") (cond ((and (fboundp 'pipenv-project-p) (pipenv-project-p) (executable-find "pipenv"))
(executable-find "cut") (executable-find "sed") (executable-find "xargs")) (setq doom-modeline-env-parser 'doom-version-parser--python)
(setq doom-modeline-env-command (setq doom-modeline-env-command "pipenv")
"pipenv run python --version 2>&1 | cut -d' ' -f2 | sed -n '1p' | xargs echo 'Pipenv'")) (setq doom-modeline-env-command-args '("run" "python" "--version")))
((and doom-modeline-python-executable ((and doom-modeline-python-executable
(executable-find doom-modeline-python-executable) (executable-find doom-modeline-python-executable))
(executable-find "cut") (executable-find "sed")) (setq doom-modeline-env-parser 'doom-version-parser--python)
(setq doom-modeline-env-command (setq doom-modeline-env-command doom-modeline-python-executable)
(concat doom-modeline-python-executable " --version 2>&1 | cut -d' ' -f2 | sed -n '1p'")))))) (setq doom-modeline-env-command-args '("--version"))))))
(add-hook 'ruby-mode-hook (add-hook 'ruby-mode-hook
(lambda () (lambda ()
(when (and (executable-find "ruby") (setq doom-modeline-env-command "ruby")
(executable-find "cut") (executable-find "sed")) (setq doom-modeline-env-command-args '("--version"))
(setq doom-modeline-env-command (setq doom-modeline-env-parser 'doom-version-parser--ruby)))
"ruby --version 2>&1 | cut -d' ' -f2 | sed -n '1p'"))))
(add-hook 'perl-mode-hook (add-hook 'perl-mode-hook
(lambda () (lambda ()
(when (and (executable-find "perl") (executable-find "cut") (setq doom-modeline-env-command "perl")
(executable-find "tr") (executable-find "sed")) (setq doom-modeline-env-command-args '("--version"))
(setq doom-modeline-env-command (setq doom-modeline-env-parser 'doom-version-parser--perl)))
"perl --version 2>&1 | cut -d'(' -f2 | cut -d')' -f1 | tr -d 'v' | sed -n '2p'"))))
(add-hook 'go-mode-hook (add-hook 'go-mode-hook
(lambda () (lambda ()
(when (and (executable-find "go") (executable-find "cut") (setq doom-modeline-env-command "go")
(executable-find "tr") (executable-find "sed")) (setq doom-modeline-env-command-args '("version"))
(setq doom-modeline-env-command (setq doom-modeline-env-parser 'doom-version-parser--go)))
"go version 2>&1 | cut -d' ' -f3 | tr -d 'go' | sed -n '1p'"))))
(add-hook 'elixir-mode-hook (add-hook 'elixir-mode-hook
(lambda () (lambda ()
(when (and (executable-find "iex") (setq doom-modeline-env-command "iex")
(executable-find "cut") (executable-find "sed")) (setq doom-modeline-env-command-args '("--version"))
(setq doom-modeline-env-command (setq doom-modeline-env-parser 'doom-version-parser--elixir)))
"iex --version 2>&1 | cut -d' ' -f2 | sed -n '1p'"))))
(add-hook 'rust-mode-hook (add-hook 'rust-mode-hook
(lambda () (lambda ()
(when (and (executable-find "rustc") (setq doom-modeline-env-command "rustc")
(executable-find "cut") (executable-find "sed")) (setq doom-modeline-env-command-args '("--version"))
(setq doom-modeline-env-command (setq doom-modeline-env-parser 'doom-version-parser--rustc)))
"rustc --version 2>&1 | cut -d' ' -f2 | sed -n '1p'"))))
;; Ensure modeline is inactive when Emacs is unfocused (and active otherwise) ;; Ensure modeline is inactive when Emacs is unfocused (and active otherwise)

86
doom-version-parser.el Normal file
View file

@ -0,0 +1,86 @@
;;; doom-version-parser.el --- A version parser for doom-modeline -*- lexical-binding: t -*-
;; Copyright (C) 2019 Justin Barclay
;; Version: 1.4.5
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;
(require 'subr-x)
(defun doom-version-parser--ruby (line)
(car (split-string
(cadr
(split-string line))
"p")))
(defun doom-version-parser--elixir (line)
(cadr
(split-string line)))
(defun doom-version-parser--rustc (line)
(car
(split-string
(cadr
(split-string line))
"-")))
(defun doom-version-parser--go (line)
(cadr
(split-string
(cadr
(cdr
(split-string
line)))
"go")))
(defun doom-version-parser--perl (line)
(cadr
(split-string
(car
(split-string
(cadr
(split-string line "("))
")"))
"v")))
(defun doom-version-parser--python (line)
(cadr
(split-string line)))
(defun doom-version-parser--get (prog args callback)
"Starts a sub process using prog and applies the args to the sub process.
Once it recieves information from STDOUT, it closes off the subprocess and
passes on the information into the callback.
Ex: (doom-version-parser--get \"ruby\" '(\"version\") (lambda (line) (message (doom-modeline-parser--ruby)))"
(let ((proc (apply 'start-process
(append ;; Flaten process-args into a single list so we can handle variadic length args
(list "doom-modeline-prog" "doom-modeline-prog" prog)
args)))
(parser callback))
(set-process-filter proc (lambda (proc1 line)
(defvar old-buffer-query-functions kill-buffer-query-functions) ;; Store old query function
(setq kill-buffer-query-functions nil) ;; No need to query user when we kill this buffer and process
(kill-process proc1) ;; Clean up after ourselves
(kill-buffer "doom-modeline-prog")
(setq kill-buffer-query-functions old-buffer-query-functions) ;; let's restore everthing
(funcall parser line)))
nil))
(provide 'doom-version-parser)
;;; doom-version-parser.el ends here

View file

@ -0,0 +1,71 @@
;;; doom-version-parser-test.el --- Unit tests for doom-version-parser -*- lexical-binding: t; -*-
;; Copyright (C) 2019 Justin Barclay
;; This file is not part of GNU Emacs.
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;
;;; Commentary:
;;
;; Unit tests for doom-version-parser
;;
;;; Code:
(ert-deftest doom-version-parser--ruby/parse-ruby-version-string ()
(should
(string= (doom-version-parser--ruby "ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-darwin16]")
"2.3.3")))
(ert-deftest doom-version-parser--elixir/parse-elixr-version-string ()
(should
(string= (doom-version-parser--elixir "IEx 1.7.4 (compiled with Erlang/OTP 21)")
"1.7.4")))
(ert-deftest doom-version-parser--rustc/parse-rustc-version-string ()
(should
(string= (doom-version-parser--rustc "rustc 1.32.0-nightly (14997d56a 2018-12-05)")
"1.32.0")))
(ert-deftest doom-version-parser--go/parse-go-version-string ()
(should
(string= (doom-version-parser--go "go version go1.11.4 darwin/amd64")
"1.11.4")))
(ert-deftest doom-version-parser--perl/parse-perl-version-string ()
(should
(string= (doom-version-parser--perl
"This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)
Copyright 1987-2013, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using \"man perl\" or \"perldoc perl\". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.")
"5.18.2")))
(ert-deftest doom-version-parser--python/parse-python-version-string ()
(should
(string= (doom-version-parser--python "Python 2.7.15")
"2.7.15")))
;;; doom-version-parser-test.el ends here