使用 bash 在已启动的 Xorg 应用程序中打开文档

使用 bash 在已启动的 Xorg 应用程序中打开文档

有没有办法告诉已经运行的 x 程序从 bash 打开文件?(即不调用程序的新实例。)虽然我是在的背景下提出这个问题的xstata-mp,但我更感兴趣的是,这种解决方案是否存在一般来说用于 Xorg 应用程序。

我有一个 x 应用程序(xstata-mp,专有,正如您将了解到的,这对于这个问题很重要),它运行良好。我设法编写了一个不错的启动脚本,它首先检查是否xstata-mp已经在运行,如果是,则将其置于前台,否则启动它。就像这个问题的可接受答案

我的问题是,有时我想打开一个文档xstata-mp被(例如,.dta数据文件、.do脚本文件、帮助文件等)使用.sthlp。如果我双击此类文件的图标,或者选择图标并在运行<ENTER>时点击xstata-mp,则启动脚本将被调用(它在文件的部分中引用)exec并提升到可见窗口的顶部,但不打开文档。xstata-mp.desktopxstata-mp

不管怎样,检查pidof一下xstata-mp 才不是xstata-mp如果我在其中打开多个文档(例如,使用<CTRL>-O),则启动一个新流程;Firefox与多个选项卡/站点形成对比。

这是我想要修改的启动脚本:

# Check if xstata-mp v17 is running
exit_code_pidof_xstata_mp=$(pidof /usr/local/stata17/xstata-mp)

# if xstata-mp v17 IS NOT running, then launch it with argument $1
if [ -z "$exit_code_pidof_xstata_mp" ]
  then
    /usr/local/stata17/xstata-mp -q $1; exit >/dev/null
 # but if xstata-mp v17 IS running, then bring it to front instead
 else
  wmctrl -ia "$(wmctrl -lp | grep "$(pgrep /usr/local/stata17/xstata-mp)" | tail -1 | awk '{ print $1 }')"; exit > /dev/null
  fi

答案1

首先,你应该找到打开文档的正确命令。因此,尝试运行以下命令并查看结果。

/usr/local/stata17/xstata-mp --help

当然这是关键部分。在这里你完全依赖程序的功能。如果它不提供这个选项,那么你就无法做到,因为 bash 所能做的就是启动另一个程序我从 上下载了 9.4 MB 的 399 页用户手册史塔塔公司,没有关于如何使用的提示xstata-mp

也许该-q选项已经是您想要的。但让我们假设将另一个文档添加到已运行的实例的正确选项xstata-mp-a(如在 VS Code 中code -a:)。那么您所要做的就是在else语句下方添加以下行:

/usr/local/stata17/xstata-mp -a "$1"

它将打开您的文档并显示当前窗口。

答案2

是的:有一种方法可以告诉已经运行的 x 程序从 bash 打开一个文件!

因此,根据 StataCorp 技术支持人员的提示,结果是xdotoolsudo apt install xdotool(如果您的系统上还没有安装,可以使用 进行安装)为我的问题提供了一种解决方案。摘自项目网站:

xdotool让您模拟键盘输入和鼠标活动、移动和调整窗口大小等。它使用 X11 的 XTEST 扩展和其他 Xlib 函数实现这些功能。

⚠️ 注意:如果您正在使用 Wayland,请注意该软件将无法正常工作。⚠️

使用xdotool,您可以搜索窗口并移动、调整大小、隐藏和修改窗口属性(例如标题)。如果您的窗口管理器支持,您可以使用xdotool切换桌面、在桌面之间移动窗口以及更改桌面数量。

为了解决我的问题xdotool,我需要创建一个xdotool我正在调用的脚本statadoc.xdo

#!/usr/bin/xdotool
search --name "Stata/MP"
type --window %1 '$1 ' '$2'
key --window %1 Return

关于这个简短脚本的一些评论:

  1. 路径可能是 以外的其他路径/usr/bin/xdotool,因此请务必确认是否具有which xdotool或类似的路径。
  2. 第二行将部分匹配"Stata/MP 17.0"上面提供的字符串的名称。这很有用,例如,将版本升级到 17.1 或 18.x 不会破坏脚本。该search命令标识了我想要与之交互的 X 应用程序窗口。
  3. xdotool脚本接受参数,遵循bash类似$1$2等的约定。
  4. 该命令实际上输入了提供的文本 - 在我的例子中,是第 2 行的命令标识的第 1 个窗口中提供的两个文本和字符串参数type的内容(在我的例子中也是唯一一个) 。$1$2search
  5. key命令将<ENTER>(或<RETURN>如果您愿意)发送到同一个 Stata 窗口。

现在让我们看一下我修改后的启动脚本,它statadoc.xdo在倒数第三行调用(我在前面添加了一个部分来识别所提供的参数是否指示特定的 Stata 文件类型 - 需要不同的使用命令来优雅地处理每个...我的例子并不完整,但这些是我在大部分工作中使用的文件类型):

# Check whether there IS NOT an argument. If not, do nothing.
if [ -z "$1" ]
  then
    break
 # Otherwise, set prefix to default value, and then check 
 # whether file name ends in .hlp, .sthlp, .ado, .do, or .gph
 else
  prefix="use "
  if [ ${1##*.} = "hlp" ] || [ ${1##*.} = "sthlp" ] || [ ${1##*.} = "ado" ] || [ ${1##*.} = "do"  ]
    then
      # If the filename DOES end in one of those four prefixes then
      # change prefix to "doedit" so Stata opens the document with 
      # the do-file editor.
      prefix="doedit "
    fi
  # If the filename ends in .gph, then change prefix to "doedit" so 
  # Stata opens the document with the graph viewer/editor.
  if [ ${1##*.} = "gph" ]
    then
      prefix="graph use "
    fi
  break
  fi

# Check if xstata-mp v17 is running
exit_code_pidof_xstata_mp=$(pidof /usr/local/stata17/xstata-mp)

# if xstata-mp v17 IS NOT running, then launch it with argument $1
if [ -z "$exit_code_pidof_xstata_mp" ]
  then
    /usr/local/stata17/xstata-mp -q $1; exit >/dev/null
 # but if xstata-mp v17 IS running, then bring it to front instead
 else
  # First, call statadoc.xdo with the prefix as the first argument, 
  # and the supplied file path as the second argument 
  /usr/share/stata17/bin/statadoc.xdo "$prefix" " $1"
  wmctrl -ia "$(wmctrl -lp | grep "$(pgrep /usr/local/stata17/xstata-mp)" | tail -1 | awk '{ print $1 }')"; exit > /dev/null
  fi

注意:这是在 Xorg 上运行 Gnome 的解决方案。

相关内容