Linux下emacs gui如何后台启动?

注:此后台启动非emacs daemon模式

有没有好用的alias,平时我都是在终端输入emacs打开emacs gui,但通常这时终端也会被占用,除非我加上 &

而像gvim,或者vscode调用时不用加 & 也不会占用终端的

而像alias emacs='emacs &'这样的,又不能直接使用emacs filename 或者emacs -nw

1 个赞

可能我没有完全理解你的需求,emacsclient不行么?

emacsclient的话其实就是emacs daemon了,我并不想直接手动调用emacs --daemon,而是我手动调用emacs gui时,根据我对server的配置来启动daemon,但调用emacs gui会同时占用我的终端

可以写一个函数

ec() { emacs "$1" & ; }

Ctrl-Z 放到后台不行嘛

如果只是gui,我之前实现一个类似的

nohup emacs "$@" &> /dev/null & disown

但对于emacs -nw来说是无效的

双击图标应该就是后台启动吧

emacs直接卡死

emacsclient -c -n

可以考虑用终端复用器

Mac 中 Bash 下这么可以(关掉终端 Emacs 也不会关掉)

bash-3.2$ emacs -Q & disown $!

Zsh 下这么也可以

zsh$ emacs -Q & disown

参考:

可能超出了题主的要求。。。

我把下面的内容保存成了一个名为 run-emacs 的脚本:

#!/bin/bash

EMACS=/usr/local/bin/emacs
EMACSCLIENT=/usr/local/bin/emacsclient

export PATH="/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
export LC_CTYPE=zh_CN.UTF-8
export LC_ALL=

ARCH=`uname`


if [ ! -f $EMACS ]; then
    echo "Can't find proper executable emacs..."
    exit 1
fi

_is_emacs_daemon_started () {
    netstat -nl 2> /dev/null | awk '{print $NF}' | grep -q "emacs.*server"
}

_is_emacs_window_exist () {
    _is_emacs_daemon_started &&         $EMACSCLIENT -e '(<= 2 (length (visible-frame-list)))' | grep -q -x t
}

_raise_emacs() {
    if [ $ARCH = 'Linux' ]; then
        which wmctrl > /dev/null 2>&1 && wmctrl -xa "emacs.Emacs"
    elif [ $ARCH = 'Darwin' ]; then
        osascript -e 'tell application "Emacs" to activate'
    else
        echo "Unsupported platform"
    fi
}

start_emacs ()
{
    $EMACS --daemon
    return $?
}

main () {
    _is_emacs_daemon_started
    if [ $? -ne 0 ] ; then
        start_emacs
        if [ $? -eq 0 ]; then
            echo ' [sucess]'
        else
            echo ' [faild]'
            return 1
        fi
    fi

    while [ 1 ]; do
        _is_emacs_daemon_started
        if [ $? -ne 0 ]; then
            echo "Waiting emacs to be started..."
            sleep 1
        else
            break
        fi
    done

    # Simply return if --daemon is set. This is only used by systemd.
    if [ "$1" = "--daemon" ]; then
        return 0
    fi

    # Get arguments passed to emacsclient.
    local args=""
    while getopts tnc var; do
        case $var in
            t)
                args="-t";;
            n)
                args="-n";;
            c)
                args="-c";;
            *)
                printf "Usage: %s [-t/-n] [-c] file:line" $0
                ;;
        esac
    done
    shift $(($OPTIND - 1))

    if [ -z "$args" ]; then
        if [ "$ARCH" = 'Linux' ]; then
            if [ -z $DISPLAY ]; then
                # Always opens new frame if working in command-line mode (without X).
                args="-t $args"
            else
                # Don't wait if working under X.
                args="-n  $args"
            fi
        elif [ "$ARCH" = 'Darwin' ]; then
            args="-n"
        fi
    fi

    _is_emacs_window_exist || args="$args -c"

    $EMACSCLIENT $args -u "$@"
    if [ $? -eq 0 ]; then
        _raise_emacs
    fi
}

main "$@"

然后在 .bashrc 中添加:


function emacs_edit ()
{
    local fn=
    local ln=
    local args=

    while [ $# -ne 0 ] ; do
        if [[ "$1" =~ "-" ]]; then
            if [ -z "$args" ]; then
                args="$1"
            else
                args="$args $1"
            fi
        else
            fn=`expr "$1" : '\([^:]*\):.*' '|' $1`
            ln=`expr "$1" :  '[^:]*:\(.*\)'` # line_info
            break
        fi
        shift 1
    done

    if [ -z $ln ]; then
        run-emacs $args $fn
    else
        run-emacs $args "+$ln" $fn
    fi
}

alias ee=emacs_edit
alias eet="emacs_edit -t"
alias edit=emacs_eidt

然后, shell 中输入 ee filename , 如果有已经启动的 emacs daemon ,则直接使用 emacsclient 打开文件,并聚焦到 Emacs 窗口。如果没有 daemon,则打开一个 emacs daemon,然后再调用 emacsclient. 两种情况下都不会占用终端。

eetee 类似,但会在终端中使用 tty 方式 打开文件。

直接双击图标开一个GUI Emacs,里面启动server-mode,在终端直接用emacsclient开文件。

非常感谢你的回复,我试一下

根据大家的回复,下午研究了一下,找到了比较适合我自己的方式,多谢各位的帮助

EMACS=/usr/bin/emacs
GUI=0
ARGS="$@"
ARRAY=("-nw" "--no-window-system" "--batch" "--help")

for arg in $ARGS; do
    for keyword in "${ARRAY[@]}";do
        if [ $keyword = $arg ];then
            GUI=1
            break
        fi
    done
    if [ $GUI -eq 1 ]; then
        break
    fi
done

if [ $GUI -eq 1 ]; then
    $EMACS $ARGS
else
    $EMACS $ARGS &> /dev/null &
    # nohup $EMACS $ARGS &> /dev/null & disown
fi
1 个赞

@lululau @seagle0128 我使用i3wm,没有图标可点击,还是习惯于直接终端输入

@cireu 终端复用器的话有些复杂了

@xuchunyang emacs直接加&对于需要打开文件或者需要某些参数的操作不太适用

i3有C-d (dmenu)可用啊

你的问题是两个吧?

  1. 怎么传递参数
  2. 怎么后台启动

而且这两个问题不相干,你要用 Shell Function 或者单独的脚本来处理第一个问题,至于第二问题,& 配合上 disown 可以解决,在我这里测试的话。

我经常在终端cd到某个目录,然后用emacs打开文件,mod+d不使用这种场景

确实是这样,但emacs是相同的二进制,传递不同的参数打开gui,或者no-window-system,如果只是对于打开gui直接加&是对的,对于no-window-system加&就不适用了,因为no-window-system本来就一定要占用终端的