Dan*_*son 16 shortcuts launcher
我想模仿在 Mac OS X 上使用 Alfred,如果你在搜索后尝试打开一个应用程序,它只会在程序尚未运行时打开一个新窗口,否则它会将焦点设置在当前正在运行的该应用程序的实例。无论如何要更改启动器的默认行为以在打开新窗口之前检查这一点?
4 月 7 日更新:添加了一个不同的版本并找到了 Albert,请参阅下面的更新和奖励!!!
关于破折号功能:您已经问过“无论如何要更改启动器的默认行为以在打开新窗口之前检查这一点”。基本答案是,不,作为普通用户,您无法将该行为添加到 dash。然而,如果有一个统一范围的开发人员愿意实现它,如果你有决心并愿意学习,你可以接近他们或自己开发一个。我的编码技能非常有限,因此我使用 shell 脚本和脚本的可用图形前端作为解决方法。
原帖:
我写了一个脚本,它使用 zenity 对话和 wmctrl 来实现你的要求。请注意,这是一个图形脚本,这意味着它只能在 Windows 中使用,在 GUI 中,如果您尝试在 tty 中启动某些东西,它将不起作用。此外,据我所知,阿尔弗雷德做的事情完全一样。您可以为其创建桌面快捷方式或启动器快捷方式,如此处和此处所述。
#!/bin/bash
# Author: Serg Kolo
# Description: A launcher script that checks whether
# or not a window of a particular program already exists
# If a window of such program is open, bring it to focus
# Otherwise - launch a new window
# Written for https://askubuntu.com/q/440142/295286
# Date: April 6 , 2015
#
MYPROG=$( zenity --entry --title='MY LAUNCHER' --text='Type the name of application to run' )
sleep 0.5
wmctrl -lx | awk '{print $3}' | grep -i "$MYPROG"
if [ $? -eq 0 ]; then
sleep 1
wmctrl -xa $MYPROG
#as an alternative try the line bellow
#wmctrl -a $MYPROG
exit 1
else
$MYPROG &
exit 0
fi
Run Code Online (Sandbox Code Playgroud)
旁注:在之前的版本中,脚本使用 echo $? 来测试之前的表达式是否成功退出。根据 muru 的建议(来自编辑),我将代码更改为更紧凑的版本,因此我建议您查看以前的版本和当前版本。
此外,以前wmctrl -a $MYPROG无法测试 google-chrome 或chromium-browser;由于某些愚蠢的原因,某些程序的窗口的 WM_CLASS 属性大写,而 由 列出的程序dpkg --get-selections是小写的(只需阅读man wmctrl并运行wmctrl -lx,您就会知道)。添加 -ax 应该解决这个问题。该脚本显示已经打开的铬窗口,因为它应该
另一件事 - wmctlr 有点奇怪,因为它有时需要延迟(在另一个脚本中使用过它),所以我不得不添加sleep 1行。以前它会在 Firefox 中打开和关闭,但现在可以正常工作。
运行中的脚本
在下面的动画中,您可以看到在第一次运行脚本时,打开了一个 Firefox 实例,脚本将焦点切换到该窗口;在第二次测试中,我打开了 google-chrome 的新实例,该实例以前未打开过。(旁注:如果您对桌面感到好奇,顺便说一下,那就是带有 cairo Dock 的 openbox)
根据评论中的建议,删除嵌入式动画,仅发布链接。如有破损请举报! http://i.stack.imgur.com/puuPZ.gif
更新,4 月 7 日
我对脚本进行了一些改进,使所有程序都列在 zenity 的下拉输入框中。现在用户不必记住每个程序,而只需使用箭头键滚动浏览它们的列表或打开下拉菜单即可。此外,这个改进的版本不是按名称而是按窗口 id 提升窗口,这提供了更好的性能。请注意,我浏览 .desktop 文件的方式有点多余,使用了两次 cut 命令,但由于我的 script-fu 到目前为止还不是那么好,这就是我所能做的。欢迎提出改进建议!
#!/bin/bash
# Author: Serg Kolo
# Description: Second version of a launcher script that checks whether
# or not a window of a particular program already exists
# If a window of such program is open, bring it to focus
# Otherwise - launch a new window
# Written for https://askubuntu.com/q/440142/295286
# Date: April 7 , 2015
#
set -x
MYPROG=$(zenity --entry --text 'Select program from list' --entry-text $(ls /usr/share/applications/*.desktop | cut -d'/' -f5 | cut -d'.' -f1 | xargs echo))
sleep 0.5
# Do we have a window of such program ?
wmctrl -lx| awk '{print $3}' | grep -i $MYPROG
if [ $? -eq 0 ]; then
sleep 0.5 # if yes, find that window id, and raise it
WINID=$(wmctrl -lx | grep -i $MYPROG | awk 'NR==1{print $1}')
wmctrl -ia $WINID &
# exit 0
else
echo $MYPROG | grep -i libreoffice
if [ $? -eq 0 ]
then
MYPROG=$(echo $MYPROG | sed 's/-/ --/g')
fi
$MYPROG &
# exit 0
fi
Run Code Online (Sandbox Code Playgroud)

奖金:
我实际上找到了Albert,它是 Alfred 的 Linux 版本,但我自己没有尝试过。不过值得一试。然而,正如雅各布已经指出的,它仍然有问题。
有一个名为 Gnome-Do 的应用程序,它的图形看起来与 Alfred 相似,但它没有与此脚本相同的功能。

如果您喜欢这个脚本,请告诉我,如果有任何需要修复的地方,如果您觉得有用,请不要忘记为答案点赞
下面是一个可用作 Dash 替代方案的脚本,用于运行您的问题中所述的应用程序。
它存在一个与 Dash 具有相同功能的窗口;如果键入应用程序的一个或多个字符,应用程序将出现在列表中。按下Enter以启动或启动应用程序,具体取决于它是否已经在运行。
您可以通过快捷键组合调用它,或在启动器中设置一个图标以类似于 Dash(见下文)使用它,或两者兼而有之。

#!/usr/bin/env python3
import subprocess
import os
import getpass
import time
user = getpass.getuser()
get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
skip = ["%F", "%U", "%f", "%u"]; trim = ["chrome", "chromium", "nautilus"]
def apply(command):
if "libreoffice" in command:
proc = [l.split()[0] for l in get("ps -u "+user).splitlines() if "soffice.bin" in l]
module = command.split("--")[-1]
time.sleep(0.1)
try:
ws = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if process in w and module in w.lower()] for process in proc], [])[0]
subprocess.call(["wmctrl", "-ia", ws])
except IndexError:
subprocess.Popen(["/bin/bash", "-c", command+"&"])
else:
check = command.split("/")[-1][:14]
proc = [p.split()[0] for p in get("ps -u "+user).splitlines() if check in p]
time.sleep(0.5)
try:
ws = sum([[w.split()[0] for w in get("wmctrl -lp").splitlines() if process in w] for process in proc], [])
if command == "nautilus":
real_window = [w for w in ws if "_NET_WM_WINDOW_TYPE_NORMAL" in get("xprop -id "+w)][0]
else:
real_window = ws[0]
subprocess.call(["wmctrl", "-ia", real_window])
except IndexError:
subprocess.Popen(["/bin/bash", "-c", command+"&"])
# default directories of .desktop files; globally, locally, LibreOffice- specific when separately installed
globally = "/usr/share/applications"; locally = os.environ["HOME"]+"/.local/share/applications"; lo_dir = "/opt/libreoffice4.4/share/xdg"
# create list of .desktop files; local ones have preference
local_files = [it for it in os.listdir(locally) if it.endswith(".desktop")]
global_files = [it for it in os.listdir(globally) if it.endswith(".desktop")]
lo_spec = [it for it in os.listdir(lo_dir) if it.endswith(".desktop")] if os.path.exists(lo_dir) else []
for f in [f for f in local_files if f in global_files]:
global_files.remove(f)
for f in [f for f in local_files if f in lo_spec]:
lo_spec.remove(f)
dtfiles = [globally+"/"+f for f in global_files]+[locally+"/"+f for f in local_files]+[lo_dir+"/"+f for f in lo_spec]
# create list of application names / commands
valid = []
for f in dtfiles:
content = open(f).read()
if all(["NoDisplay=true" not in content,"Exec=" in content]):
lines = content.splitlines()
name = [l.replace("Name=", "") for l in lines if "Name=" in l][0]
command = [l.replace("Exec=", "") for l in lines if all(["Exec=" in l, not "TryExec=" in l])][0]
valid.append((name, command))
valid.sort(key=lambda x: x[0])
# create zenity list + window
list_items = '"'+'" "'.join([f[0] for f in valid])+'"'
proposed = 'zenity --list --text "Type one or more characters... " --column="Application List" '+\
'--title="Dash the Second" --height 450 --width 300 '+list_items
try:
choice = subprocess.check_output(["/bin/bash", "-c", proposed]).decode("utf-8").strip().split("|")[0]
command = [r[1] for r in valid if r[0] == choice][0]
# command fixes:
for s in skip:
command = command.replace(" "+s, "")
for t in trim:
if t in command:
command = t
apply(command)
except subprocess.CalledProcessError:
pass
Run Code Online (Sandbox Code Playgroud)
脚本需要wmctrl安装:
sudo apt-get install wmctrl
Run Code Online (Sandbox Code Playgroud)
然后:
dash_alternative.py将其添加到快捷键组合:选择:系统设置>“键盘”>“快捷方式”>“自定义快捷方式”。单击“+”并添加命令:
python3 /path/to/dash_alternative.py
Run Code Online (Sandbox Code Playgroud)当脚本运行时,它会列出所有应用程序,以/usr/share/applications. 它搜索.dektop文件,创建所有应用程序名称(从第一个“Name=”行)和运行应用程序的命令(从第一个“Exec=”行)的列表。
随后,创建 Zenity 列表,以排序方式呈现所有应用程序。
如果选择了应用程序,则脚本会在运行应用程序时查找正在运行的进程列表。如果是这样,相应的窗口就会升起。如果不是,则打开一个新实例。
要在12.04上运行脚本(因为原始问题被标记,12.04只需将 shebang 更改为#!/usr/bin/env python并通过命令运行它
python /path/to/dash_alternative.py
Run Code Online (Sandbox Code Playgroud)据我测试,该脚本工作正常。命令及其(非)对应的进程名称(例如LibreOffice<> soffice.bin)、不同的窗口类型(nautilus除了“真实”窗口之外还有几种不同的窗口类型)、每个应用程序的多个 pid(Chromium, Google-chrome)可能导致异常,我在示例中修复了这些问题以上。如果有人遇到问题,请提及。
将下面的图标(右键单击 > 安全为)另存为 dash_alternative.png

将下面的代码复制到一个空文件中,另存~/.local/share/applications为dash_thesecond.desktop. 为/path/to/dash_alternative.py(脚本)和/path/to/dash_alternative.png(图标)设置正确的路径
[Desktop Entry]
Name=Dash the Second
Exec=python3 /path/to/dash_alternative.py
Icon=/path/to/dash_alternative.png
Type=Application
Hidden=false
Run Code Online (Sandbox Code Playgroud)将.desktop文件拖到启动器上:
| 归档时间: |
|
| 查看次数: |
4332 次 |
| 最近记录: |