[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Run powershell as a shell within Emacs on Windows
From: |
D Chiesa |
Subject: |
Run powershell as a shell within Emacs on Windows |
Date: |
Tue, 27 May 2008 15:05:05 -0700 |
Another thing I put together - the ability to run Windows Powershell as a
shell within emacs. For those who don't follow the whims of Redmond,
Powershell is a shell for Windows, featuring a new script language . It is
the replacement for cmd.exe and batch files.
If Powershell were a normal shell, running it within emacs would be really
simple: just set explicit-shell-file-name and then
explicit-powershell.exe-args , and then M-x shell. But Powershell does not
emit a prompt when its input is redirected (aka when it is in
non-interactive mode), and that makes for bad quality of life. There is
also a weird issue with powershell and buffer sizes - it clips its output to
the buffer size, and so if you resize emacs you need to tell the inferior
powershell you've done so, to avoid clipping or line-wrapping in the shell
buffer.
That felt like enough baling-wire and duct tape to justify an elisp file to
me. So here is powershell.el. This is not an editing mode for powershell
script; it is not "powershell mode". (That has been solved by someone else).
It is a shell mode for running powershell within emacs.
I run it on GNU Emacs (for Windows) 22.2.1 (i386-mingw-nt6.0.6001).
This thing is mostly interesting to users on Windows, who run powershell.
This could be administrative users, developers, hybrids, and that sort of
thing. I am happy to have powershell.el included in future emacs shipments
if that is appropriate. (I don't know if that is overly presumptuous or
not. )
Is this useful if I post this kinda stuff here?
----
;; powershell.el, version 0.1
;;
;; Author: Dino Chiesa
;; Thu, 10 Apr 2008 11:10
;;
;; Run Windows PowerShell v1.0 as an inferior shell within emacs. Tested
with emacs v22.2.
;;
;; TODO:
;; test what happens when you expand the window size beyond the
maxWindowWidth for the RawUI
;; make everything configurable (Powershell exe, initial args, powershell
prompt regexp)
;; implement powershell launch hooks
;; prevent backspace from deleting the powershell prompt? (do other shells
do this?)
;;
(require 'shell)
(defun powershell-gen-window-width-string ()
(concat "$a = (Get-Host).UI.RawUI\n"
"$b = $a.WindowSize\n"
"$c = $a.WindowSize\n"
"$b.Width = 19999\n"
"$c.width = " (number-to-string (window-width)) "\n"
"$a.BufferSize = $b\n"
"$a.WindowSize = $c")
)
(defvar powershell-prompt-pattern "PS [^#$%>]+>"
"Regexp for powershell prompt. This isn't really used, because I couldn't
figure out how to get it to work."
)
(defgroup powershell nil
"Running shell from within Emacs buffers."
:group 'processes
)
(defcustom powershell-need-rawui-resize t
"set when powershell needs to be resized"
:group 'powershell
)
;;;###autoload
(defun powershell (&optional buffer)
"Run Powershell, by invoking the shell function. See the help for shell
for more details.
\(Type \\[describe-mode] in the shell buffer for a list of commands.)"
(interactive
(list
(and current-prefix-arg
(read-buffer "Shell buffer: "
(generate-new-buffer-name "*PowerShell*")))))
; get a name for the buffer
(setq buffer (get-buffer-create (or buffer "*PowerShell*")))
(let (
(tmp-shellfile explicit-shell-file-name)
)
; set arguments for the powershell
exe.
; This needs to be tunable.
(setq explicit-shell-file-name
"c:\\windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe")
(setq explicit-powershell.exe-args '("-Command" "-" )) ; interactive,
but no command prompt
; launch the shell
(shell buffer)
; restore the original shell
(if explicit-shell-file-name
(setq explicit-shell-file-name tmp-shellfile)
)
)
(let (
(proc (get-buffer-process buffer))
)
; This sets up the powershell RawUI screen width. By default,
; the powershell v1.0 assumes terminal width of 80 chars.
;This means input gets wrapped at the 80th column. We reset the
; width of the PS terminal to the window width.
(add-hook 'window-size-change-functions 'powershell-window-size-changed)
(powershell-window-size-changed)
; ask for initial prompt
(comint-simple-send proc "prompt")
)
; hook the kill-buffer action so we can kill the inferior process?
(add-hook 'kill-buffer-hook 'powershell-delete-process)
; wrap the comint-input-sender with a PS version
; must do this after launching the shell!
(make-local-variable 'comint-input-sender)
(setq comint-input-sender 'powershell-simple-send)
; set a preoutput filter for powershell. This will trim newlines after
the prompt.
(add-hook 'comint-preoutput-filter-functions
'powershell-preoutput-filter-for-prompt)
;(run-hooks 'powershell-launch-hook)
; return the buffer created
buffer
)
(defun powershell-window-size-changed (&optional frame)
; do not actually resize here. instead just set a flag.
(setq powershell-need-rawui-resize t)
)
(defun powershell-delete-process (&optional proc)
(or proc
(setq proc (get-buffer-process (current-buffer))))
(and (processp proc)
(delete-process proc))
)
;; This function trims the newline from the prompt that we
;; get back from powershell. It is set into the preoutput
;; filters, so the newline is trimmed before being put into
;; the output buffer.
(defun powershell-preoutput-filter-for-prompt (string)
(if
; not sure why, but I have not succeeded in using a variable here???
;(string-match powershell-prompt-pattern string)
(string-match "PS [^#$%>]+>" string)
(substring string 0 -1)
string
)
)
(defun powershell-simple-send (proc string)
"Override of the comint-simple-send function, specific for powershell.
This just sends STRING, plus the prompt command. Normally powershell is in
noninteractive model when run as an inferior shell with stdin/stdout
redirected, which is the case when running as a shell within emacs.
This function insures we get and display the prompt. "
; resize if necessary. We do this by sending a resize string to the shell,
; before sending the actual command to the shell.
(if powershell-need-rawui-resize
(and
(comint-simple-send proc (powershell-gen-window-width-string))
(setq powershell-need-rawui-resize nil)
)
)
(comint-simple-send proc string)
(comint-simple-send proc "prompt")
)
(provide 'powershell)
;; End of powershell.el
- Run powershell as a shell within Emacs on Windows,
D Chiesa <=