繁体   English   中英

在Linux上制作Sublime Text 2命令就像在MacOS X上一样

[英]Making Sublime Text 2 command on linux behave as it does on MacOS X

有很多问题要求从命令行访问Sublime Text 2编辑器。 总之,响应是使用符号链接,别名或简单的shell脚本来运行相应的sublime_text命令。 我能做到。 我想要的是使Linux版本的行为类似于MacOS版本。

在MacOS上,我有以下内容:

ln -s /Applications/Sublime\ Text\ 2.app/Contents/SharedSupport/bin/subl ~/bin/subl

然后在我的.zshrc中:

alias subl="$HOME/bin/subl -n"
export EDITOR="$HOME/bin/subl -n -w"

这样做有两件事。 它为我提供了一个subl命令,用于在新窗口中打开命令行上给出的所有文件。 subl命令不会阻止终端。 它还设置我的编辑器打开sublime文本来编辑参数,但这次它确实阻止了。 特别是$EDITOR阻塞,直到它的参数被关闭。 它不会阻止不相关的sublime文本窗口。

我可以通过以下方式在linux上实现类似的效果:

在〜/ bin / subl中:

#! /bin/zsh

$HOME/Sublime\ Text\ 2/sublime_text -n $@ &

然后在〜/ bin / subl_wait :(想想TextMate用户的mate_wait

#! /bin/zsh

exec $HOME/Sublime\ Text\ 2/sublime_text -n -w $@

然后我可以将EDITOR设置为subl_wait ,几乎可以正常工作。 subl打开文件进行编辑,不会阻止。 subl_wait打开文件进行编辑并阻止。

问题是subl_wait正在等待所有打开的文件关闭,而不仅仅是它的参数。

有可能让这个工作完美吗?

看起来我发现了这个问题。 (感谢这篇文章: http//www.sublimetext.com/forum/viewtopic.php?f = 2& t = 7003

基本点:sublime的行为有所不同,具体取决于实例是否已在运行!

如果一个实例已在运行,则linux上的sublime与MacOS的行为类似。 如果没有实例正在运行,则终端将阻塞,直到您退出sublime。

考虑到这一点,我们只需要修改脚本以确保sublime正在运行:

~/bin/subl_start

#! /bin/zsh

if [ ! "$(pidof sublime_text)" ] ; then
  # start sublime text main instance
  # echo "Starting Sublime Text 2"
  $HOME/Sublime\ Text\ 2/sublime_text &
  sleep 1 # needed to avoid a race condition
fi

~/bin/subl

#! /bin/zsh

. $HOME/bin/subl_start

exec $HOME/Sublime\ Text\ 2/sublime_text -n $@

~/bin/subl_wait

#! /bin/zsh

. $HOME/bin/subl_start

exec $HOME/Sublime\ Text\ 2/sublime_text -n -w $@

请注意,我到处都使用了-n标志。 这可能不是你的一杯茶。 如果您使用-n那么您可能还想查看close_windows_when_empty设置。

受OP的回答启发,我为Sublime Text创建了一个bash 包装脚本,它包含了你在OSX和Linux上的所有发现和运行

它的目的有三个:

  • 提供一个统一的subl CLIsublsubl上与ST自己的subl一样工作:调用ST 而不阻塞,除非明确请求等待
  • 封装了Linux上与等待相关的错误解决方法
  • 当保存或sublwait链接为sublwait ,提供一个sublwait CLI ,它自动应用--wait--wait --new-window选项,以使其适合与$EDITOR一起使用 (注意某些程序,例如npm ,需要$EDITOR仅包含可执行文件的名称 - 不支持可执行文件+选项); 还确保至少指定了一个文件。

唯一悬而未决的问题是,OP的避免竞争条件的方法 - sleep 1 - 是否足够强大。

更新 :请注意,OSX上的subl默认情况下不会放在$PATH - 您通常必须手动执行此操作。 如果你还没有这样做,脚本现在将在ST的应用程序包中找到subl ; (它按以下顺序尝试应用程序名称:'Sublime Text','Sublime Text 2','Sublime Text 3',首先在/Applications ,然后在~/Applications 。)

这是使用-h运行脚本的输出:

Multi-platform (OSX, Linux) wrapper script for invocation of Sublime Text (ST)
from the command line.

Linux:
  Works around undesired blocking of the shell (unless requested)
  and a bug when waiting for specific files to be edited.
Both platforms:
  When invoked as `sublwait`, automatically applies the
    --wait --new-window
  options to make it suitable for use with $EDITOR.

Therefore, you can to the following:
- Name this script `subl` for a CLI that supports ALL options.
  (On OSX, this will simply defer to the `subl` CLI that came with ST.)
- Place the script in a directory in your $PATH.
- In the same directory, create a symlink to the `subl` script named
  `sublwait`:
    ln -s subl sublwait
  and, if desired, add
    export EDITOR=sublwait
  to your shell profile.

请注意,如果您只使用OSX,您可以使用ST自己的subl ,只需将此脚本直接保存为sublwait

脚本来源:

#!/usr/bin/env bash

# Multi-platform (OSX, Linux) wrapper script for invocation of Sublime Text (ST)
# from the command line. Invoke with -h for details.

[[ $1 == '-h' || $1 == '--help' ]] && showHelpOnly=1 || showHelpOnly=0
[[ $(basename "$BASH_SOURCE") == 'sublwait' ]] && invokedAsSublWait=1 || invokedAsSublWait=0
[[ $(uname) == 'Darwin' ]] && isOsX=1 || isOsX=0

# Find the platform-appropriate ST executable.
if (( isOsX )); then # OSX: ST comes with a bona-fide CLI, `subl`.

  # First, try to find the `subl` CLI in the $PATH.
  # Note: This CLI is NOT there by default; it must be created by symlinking it from
  #       its location inside the ST app bundle.
  # Find the `subl` executable, ignoring this script, if named subl' as well, or a
  # script by that name in the same folder as this one (when invoked via symlink 'sublwait').
  stExe=$(which -a subl | fgrep -v -x "$(dirname "$BASH_SOURCE")/subl" | head -1)
  # If not already in the path, look for it inside the application bundle. Try several locations and versions.
  if [[ -z $stExe ]]; then
    for p in {,$HOME}"/Applications/Sublime Text"{,' 2',' 3'}".app/Contents/SharedSupport/bin/subl"; do
      [[ -f $p ]] && { stExe=$p; break; }
    done
  fi
  [[ -x $stExe ]] || { echo "ERROR: Sublime Text CLI 'subl' not found." 1>&2; exit 1; }

else # Linux: `sublime_text` is the only executable - the app itself.

  stExe='sublime_text'
  which "$stExe" >/dev/null || { echo "ERROR: Sublime Text executable '$stExe' not found." 1>&2; exit 1; }

fi

# Show command-line help, if requested.
# Add preamble before printing ST's own help.
# Note that we needn't worry about blocking the
# shell in this case - ST just outputs synchronously
# to stdout, then exits.
if (( showHelpOnly )); then

  bugDescr=$(
    cat <<EOF
works around a bug on Linux (as of v2.0.2), where Sublime Text,
if it is not already running, mistakenly blocks until it is exited altogether.
EOF
  )

  if (( invokedAsSublWait )); then

    # We provide variant-specific help here.
    cat <<EOF

Wrapper script for Sublime Text suitable for use with the \$EDITOR variable.

Opens the specified files for editing in a new window and blocks the 
invoking program (shell) until they are closed.
In other words: the --wait and --new-window options are automatically
applied.

Aside from encapsulating this functionality without the need for options
- helpful for tools that require \$EDITOR to be an executable name only -
$bugDescr

Usage: sublwait file ...

EOF
    # Note: Adding other options doesn't make sense in this scenario
    #       (as of v2.0.2), so we do NOT show ST's own help here.

  else

    cat <<EOF

Multi-platform (OSX, Linux) wrapper script for invocation of
Sublime Text (ST) from the command line.

Linux:
  Works around undesired blocking of the shell (unless requested)
  and a bug when waiting for specific files to be edited.
Both platforms:
  When invoked as \`sublwait\`, automatically applies the
    --wait --new-window
  options to make it suitable for use with \$EDITOR.

Therefore, you can to the following:
- Name this script \`subl\` for a CLI that supports ALL options.
  (On OSX, this will simply defer to the \`subl\` CLI that came with ST.)
- Place the script in a directory in your \$PATH.
- In the same directory, create a symlink to the \`subl\` script named
  \`sublwait\`:
    ln -s subl sublwait
  and, if desired, add
    export EDITOR=sublwait
  to your shell profile.

Sublime Text's own help:
------------------------
EOF

    # Finally, print ST's own help and exit.
    exec "$stExe" "$@"

  fi
  exit 0
fi


# Invoked as `sublwait`? -> automatically apply --wait --new-window options.
if (( invokedAsSublWait )); then

  # Validate parameters.
  # - We expect NO options - to keep things simple and predictable, we do NOT allow
  #   specifying additional options (beyond the implied ones).
  # - We need at least 1 file argument.
  # - As a courtesy, we ensure that no *directories* are among the arguments - ST doesn't support
  #  that properly (always waits for ST exit altogether); beyond that, however, we leave input
  #  validation to ST.
  if [[ "$1" =~ ^-[[:alnum:]]+$ || "$1" =~ ^--[[:alnum:]]+[[:alnum:]-]+$ ]]; then # options specified?
    { echo "ERROR: Unexpected option specified: '$1'. Use -h for help." 1>&2; exit 1; }
  elif (( $# == 0 )); then # no file arguments?
    { echo "ERROR: Missing file argument. Use -h for help." 1>&2; exit 1; }
  else # any directories among the arguments?
    # Note: We do NOT check for file existence - files could be created on demand.
    #       (Things can still go wrong - e.g., /nosuchdir/mynewfile - and ST doesn't
    #       handle that gracefully, but we don't want to do too much here.)
    for f in "$@"; do
      [[ ! -d "$f" ]] || { echo "ERROR: Specifying directories is not supported: '$f'. Use -h for help." 1>&2; exit 1; }
    done
  fi

  # Prepend the implied options.
  set -- '--wait' '--new-window' "$@"

fi

# Finally, invoke ST:
if (( isOsX )); then # OSX

  # `subl` on OSX handles all cases correctly; simply pass parameters through.
  exec "$stExe" "$@"

else # LINUX: `sublime_text`, the app executable itself, does have a CLI, but it blocks the shell.

  # Determine if the wait option was specified.
  mustWait=0
  if (( invokedAsSublWait )); then
    mustWait=1
  else
    # Look for the wait option in the parameters to pass through.
    for p in "$@"; do
      [[ $p != -* ]] && break # past options
      [[ $p == '--wait' || $p =~ ^-[[:alnum:]]*w[[:alnum:]]*$ ]] && { mustWait=1; break; }
    done
  fi

  if (( mustWait )); then # Invoke in wait-for-specified-files-to-close mode.

    # Quirk on Linux:
    # If sublime_text isn't running yet, we must start it explicitly first.
    # Otherwise, --wait will wait for ST *as a whole* to be closed before returning, 
    # which is undesired.
    # Thanks, http://stackoverflow.com/questions/14598261/making-sublime-text-2-command-on-linux-behave-as-it-does-on-macos-x
    if ! pidof "$stExe" 1>/dev/null; then
        # Launch as BACKGROUND task to avoid blocking.
        # (Sadly, the `--background` option - designed not to activate the Sublime Text window 
        #  on launching - doesn't actually work on Linux (as of ST v2.0.2 on Ubuntu 12.04).)
        ("$stExe" --background &)
        # !! We MUST give ST some time to start up, otherwise the 2nd invocation below will be ignored.
        # ?? Does a fixed sleep time of 1 second work reliably?
        sleep 1
    fi

    # Invoke in blocking manner, as requested.
    exec "$stExe" "$@"

  else # Ensure invocation in NON-blocking manner.

    if ! pidof "$stExe" 1>/dev/null; then # ST isn't running.
      # If ST isn't running, invoking it *always* blocks.
      # Therefore, we launch it as a background taks.
      # Invocation via a subshell (parentheses) suppresses display of the 
      # background-task 'housekeeping' info.
      ("$stExe" "$@" &)
    else # ST is already running, we can safely invoke it directly without fear of blocking.
      exec "$stExe" "$@"
    fi

  fi

fi

在Ubuntu Gnu / Linux 13.04 64位:

我只是一直在运行subl。 所以我的git配置有: core.editor=/usr/bin/subl -n -w

这就是我所需要的一切。 我用ctrl-s保存git commit文件,用ctrl-w关闭窗口,我就完成了。 但是,我必须再通过点击页面右上角的X ... 96%的完美, 真正关闭窗口。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM