Emacs shell的TERM环境变量是否可以设置为除了"dumb"以外的其他值?为了使TRAMP正常工作,我正在根据$TERM == "dumb"条件调整远程机器上.bashrc的某些部分,但是对于shell,我希望忽略这些内容(相反的方法-为TRUMP设置TERM-也适用)。
Emacs shell的TERM环境变量是否可以设置为除了"dumb"以外的其他值?为了使TRAMP正常工作,我正在根据$TERM == "dumb"条件调整远程机器上.bashrc的某些部分,但是对于shell,我希望忽略这些内容(相反的方法-为TRUMP设置TERM-也适用)。
# ~/.emacs_zsh or ~/.emacs.d/init_zsh.sh
export TERM=emacs
那么你会得到你所要求的东西:使用 M-x shell
启动的 shell 将把 TERM
设为 emacs
,而不是 dumb
。
虽然这在技术上回答了你的问题,但并不特别有用——如果你尝试它,当你启动一个 shell 时,你将得到以下结果:
zsh: can't find terminal definition for emacs
$ echo $TERM
emacs
$
shell-mode
并没有实现任何终端仿真。换句话说,dumb
恰好是使用的正确TERM
值。(请注意,确实有一些模式可以模拟终端——例如,参见M-x ansi-term
——它们设置TERM=eterm-color
或类似的值,但是它们被设计成让您使用Emacs作为可视模式下的xterm替代品来运行shell命令,而M-x shell
则被设计成让您在与输入和输出交互的同时以Emacs方式运行shell命令。)当您选择一个不受termcap支持的TERM
值时,您将会得到上述错误,并且一些程序可能会对所发生的情况感到困惑(有些甚至会拒绝运行)。如果您选择一个功能齐全的TERM
值,如xterm
,那么当程序尝试向不存在的终端仿真器发送格式化代码时,您将得到“线噪声”字符。您可能可以找到一些能力有限的termcap,以使噪声对您的影响不太大,但如果这只是让您区分Emacs交互式shell与Emacs非交互式shell或非Emacs交互式shell,那么有更好的选择。实际上,这个选择甚至还不够。因为这个特殊的shell脚本被shell-mode
和TRAMP都加载,所以上述方法仍然不能让您区分这两者——您将在两种情况下都得到emacs
而不是dumb
!因此,更好的选择就出现了:使用INSIDE_EMACS
环境变量。正如您所指出的那样,交互式shell和TRAMP默认都将TERM
设置为dumb
,但它们还设置了一个环境变量INSIDE_EMACS
。它的存在(或不存在)对于您的shell启动脚本非常有用,但对于您的用例来说,它的价值在于其值——对于交互式(M-x shell
)使用,它的值类似于25.2.2,comint
,但对于TRAMP,则是25.2.2,tramp
。因此,要检查这三种情况,您可以这样做(这也是我自己多年来在我的~/.zshrc中所做的):# Setup for all shells--Emacs or not, interactive or not, goes
# here
PATH=...
source $my_functions_file
# Now dumb terminals
if [[ "${TERM}" == "dumb" ]]; then
# Here put anything you want to run in any dumb terminal,
# even outside Emacs.
PATH=...
alias lsF='ls -F'
etc
# Now, just configs for shells inside Emacs
case ${INSIDE_EMACS/*,/} in
(comint)
do_comint_stuff
;;
(tramp)
do_tramp_stuff
;;
(term*)
# For M-x ansi-term, etc., you get a value like
# 25.2.2,term:0.96, but those shouldn't coincide with
# TERM being `dumb`, so warn....
echo "We somehow have a dumb Emacs terminal ${INSIDE_EMACS/*,/}" >&2
;;
("")
# Empty means we're $TERM==dumb but not in Emacs, do nothing
;;
(*)
# We shouldn't get here, so write a warning so we can
# figure out how else Emacs might be running a shell,
# but send it to stderr so that it won't break anything
echo "Something is wrong: INSIDE_EMACS is ${INSIDE_EMACS}" >&2
;;
esac
# finish shell setup for dumb now--the rest of the file will
# be skipped
return
fi
# Stuff for non-dumb, interactive visual, shells goes here
setup_prompt
setup_keybindings
etc
我们在case语句中不会将TERM
重置为其他值,因为正是它应该的样子。
请注意,在case语句的部分中,您可以像您在问题中提到的那样将TERM
设置为其他内容,但这是一个坏主意,因为Emacs实际上会读取并执行从TRAMP shell获得的响应,并且线路噪声会成为更大的问题。 TRAMP可以做一些非常惊人的事情,但前提是它所读取的shell输出格式符合TRAMP的期望。
最后一件事:使用上述代码时,由于dumb
终端检查嵌套在INSIDE_EMACS
检查之内,因此我们没有一个单独的地方来放置要在所有类型的Emacs生成的shell中运行的代码,包括M-x ansi-term
及其类似物。您可以在shell配置中为此编写单独的语句...但这正是~/.emacs.d/init_${SHELLNAME}.sh
的用途,因此如果您出于某种原因需要此功能,则可能是更好的选择。
INSIDE_EMACS
环境变量,而不会干扰TERM
(这似乎是一件潜在危险的事情)。 - philsTERM
的作用是告诉程序它们正在运行的终端类型,以便它们可以决定如何控制终端。TERM=dumb
是正确的,因为shell
不是一个终端。 如果您将TERM
设置为其他内容,您将欺骗查看该变量的任何程序,但结果将是错误的,因为终端本身不会按照指示的方式行事。 - jpkottaterm
。 - Tomas Varga