-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathesh-help.el
150 lines (130 loc) · 5.11 KB
/
esh-help.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
;;; esh-help.el --- Add some help functions and support for Eshell
;; Copyright (C) 2013, 2014 by Tomoya Tanjo
;; Author: Tomoya Tanjo <[email protected]>
;; URL: https://github.com/tom-tan/esh-help/
;; Package-Requires: ((dash "1.4.0"))
;; Keywords: eshell, extensions
;; 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 3 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This library adds the following help functions and support for Eshell:
;; - run-help function inspired by Zsh
;; - eldoc support
;;
;; To use this package, add these lines to your .emacs file:
;; (require 'esh-help)
;; (setup-esh-help-eldoc) ;; To use eldoc in Eshell
;; And by using M-x eldoc-mode in Eshell, you can see help strings
;; for the pointed command in minibuffer.
;; And by using M-x esh-help-run-help, you can see full help string
;; for the command.
;;; Code:
(require 'esh-cmd)
(require 'esh-mode)
(require 'em-unix)
(require 'esh-ext)
(require 'eldoc)
(require 'env)
(require 'dash)
(require 'man)
;;;###autoload
(defun setup-esh-help-eldoc ()
"Setup eldoc function for Eshell."
(interactive)
(add-hook 'eshell-mode-hook
(lambda ()
(make-local-variable 'eldoc-documentation-function)
(setq eldoc-documentation-function
'esh-help-eldoc-command))))
;;;###autoload
(defun esh-help-run-help (cmd)
"Show help for the pointed command or functions CMD.
It comes from Zsh."
(interactive
(list (esh-help-pointed-symbol)))
(cond
((eshell-find-alias-function cmd)
(describe-function (eshell-find-alias-function cmd)))
((string-match-p "^\\*." cmd)
(man (substring cmd 1)))
((eshell-search-path cmd) (man cmd))
((functionp (intern cmd)) (describe-function (intern cmd)))))
(defun esh-help-pointed-symbol ()
"Return the symbol to show the help string."
(let ((bol (save-excursion
(eshell-bol)
(point)))
(eol (save-excursion
(move-end-of-line nil)
(point))))
(when (<= bol (point))
(save-excursion
(--if-let (re-search-backward "|" bol t)
(forward-char)
(eshell-bol))
(--when-let (re-search-forward "[^\s]+" eol t)
(goto-char it)
(current-word))))))
(defalias 'esh-help--get-fnsym-args-string
(if (fboundp 'eldoc-get-fnsym-args-string)
#'eldoc-get-fnsym-args-string
#'elisp-get-fnsym-args-string)
"eldoc-get-fnsym-args-string is no longer defined in Emacs 25")
(defun esh-help-eldoc-help-string (cmd)
"Return minibuffer help string for CMD."
(cond
((string-match-p "^[/.]" cmd) nil)
((eshell-find-alias-function cmd)
(esh-help--get-fnsym-args-string (eshell-find-alias-function cmd)))
((string-match-p "^\\*." cmd)
(esh-help-eldoc-man-minibuffer-string (substring cmd 1)))
((eshell-search-path cmd) (esh-help-eldoc-man-minibuffer-string cmd))
((functionp (intern cmd)) (esh-help--get-fnsym-args-string (intern cmd)))))
(defvar esh-help-man-cache (make-hash-table :test #'equal)
"Cache of synopses scraped from system man pages.")
(defun esh-help-clear-man-cache ()
"Clear the `esh-help-man-cache'."
(interactive)
(setq esh-help-man-cache (make-hash-table :test #'equal)))
(defun esh-help-man-string (cmd)
"Return help string for the shell command CMD."
(let ((lang (getenv "LANG")))
(setenv "LANG" "C")
(let ((str (shell-command-to-string (format "%s %s | col -b"
manual-program cmd))))
(setenv "LANG" lang)
str)))
(defun esh-help-eldoc-man-minibuffer-string (cmd)
"Return minibuffer help string for the shell command CMD."
(let ((cache-result (gethash cmd esh-help-man-cache)))
(if cache-result
(unless (eql 'none cache-result)
cache-result)
(let ((str (split-string (esh-help-man-string cmd) "\n")))
(if (equal (concat "No manual entry for " cmd)
(car str))
(progn
(puthash cmd 'none esh-help-man-cache)
nil)
(puthash cmd
(->> str
(--drop-while (not (string-match-p "^SYNOPSIS$" it)))
(nth 1)
(funcall (lambda (s)
(let ((idx (string-match "[^\s\t]" s)))
(substring s idx)))))
esh-help-man-cache))))))
(defun esh-help-eldoc-command ()
"Return eldoc string for the pointed symbol."
(--when-let (esh-help-pointed-symbol)
(esh-help-eldoc-help-string it)))
(provide 'esh-help)
;;; esh-help.el ends here