アプリケーションごとにデフォルトのキーボード言語を割り当てる


11

特定のアプリケーションにデフォルトのキーボード言語を割り当てることは可能ですか?常にデフォルトのキーボード言語でアプリケーションを起動するオプションがあることは知っていますが、これは私が望んでいることではありません。

CompizConfigを使用して設定できる「固定ワークスペース」に似たものを探しています(Chromeを常にX1Y1で開くように設定し、X2Y1で端末を開くなど)。Chromeを設定する場所:チェコ語、ターミナル:英語、Spotify:英語、...


「テキスト入力」には、「ウィンドウごとに異なるソースを許可する」オプションがあります。おそらくあなたにとって正しい方向への一歩です。
Gunnar Hjalmarsson 2015

はい、ありがとうございます。私はそれについて知っています。これは私が言う必要のあるステップですが、残念ながらそれは私が達成したいことではありません。とにかくありがとう。
grongor

スクリプティングの方法があります。あなたはそれらの3つのアプリだけが必要ですか、それとも他にもありますか?スクリプトをどの程度柔軟にしたいかに応じて、それを書くのに多少時間がかかるかもしれません
Sergiy Kolodyazhnyy

@JacobVlijm Pythonの別の良い仕事のように聞こえます;)
セルギーKolodyazhnyy

回答を投稿しました。あなたの考えを教えてください
セルギー・コロディアズニー

回答:


6

前書き

以下のスクリプトは、言語メニューでのその言語の位置に従って、各ユーザー定義プログラムの言語を設定します。たとえば、注文が英語(1)、中国語(2)、ロシア語(3)の場合、Firefoxを言語2、端末を言語1、LibreOfficeを言語3に設定できます。

スクリプトは2つの部分で構成されています。1つ目は実際に機能するスクリプトで、2つ目のスクリプトは制御要素として機能します。言語設定スクリプトを起動アプリケーションとして実行し、言語を手動で変更する必要がある場合はいつでも、コントローラースクリプトへのショートカットをダブルクリックするという考え方です。

前提条件

  1. wmctrlプログラムをインストールしsudo apt-get install wmctrlます。

脚本

#!/bin/sh
# Author: Serg Kolo
# Date: August 4, 2015
# Description: This script forces assigned input languages
#              for specific windows
# Version:2

# Use this part to set programs and their respective languages
# PROG_CLASS or a running window can be found with the
# wmctrl -lx command
# If you want to add another program to the list, 
# follow the template PROG_CLASS_num=window.Class
# and bellow that $LANGnum=num


PROG_CLASS_1=gedit.Gedit
LANG1=2

PROG_CLASS_2=gnome-terminal-server.Gnome-terminal
LANG2=0

PROG_CLASS_3=Navigator.Firefox
LANG3=1


# While loop below gets the job done. 
# If you need to send languages for more programs -  copy  
# the first entry and replace  $PROG_CLASS_1 with $PROG_CLASS_num
# where num is respective number of a program
# Replace $LANGnum with the respective language number. After the "="
# post positional number of the language you want to use. 
# Remember the count starts from 0

while [ 1 ];do
  WM_CLASS=$(wmctrl -lx | awk -v search=$(printf %x $(xdotool getactivewindow)) '{ if($1~search) print $3 }' )
  CURRENT=$(gsettings get org.gnome.desktop.input-sources current| awk '{print $2}')
    case  $WM_CLASS in

      $PROG_CLASS_1)  
        if [ $CURRENT -ne  $LANG1 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG1
        fi
      ;;

      $PROG_CLASS_2) 
        if [ $CURRENT -ne  $LANG2 ];then
          gsettings set org.gnome.desktop.input-sources current $LANG2
        fi  
      ;;

       $PROG_CLASS_3) 
         if [ $CURRENT -ne  $LANG3 ];then
           gsettings set org.gnome.desktop.input-sources current $LANG3
         fi  
        ;;
    esac

    sleep 0.250

done

コントローラスクリプト

#!/bin/sh
# set -x
# Author: Serg Kolo
# Date: August 8, 2015
# Description: Controller script for set-lang.sh script
# Allows pausing and resuming execution of set-lang.sh
STATUS=$(ps -o stat -p $(pgrep -o  set-lang.sh) | awk '{getline;print }')

case $STATUS in
    T) kill -CONT $(pgrep set-lang.sh) 
       notify-send 'RESUMED'
    ;;

    S) kill -STOP $(pgrep set-lang.sh)
       notify-send 'STOPED'
    ;;

    *) exit ;;
esac 

set-lang.shスクリプト用のランチャー(.desktop)ファイル

[Desktop Entry]
Name=set-lang.sh
Comment=Script to set languages
Exec=/home/yourusername/bin/set-lang.sh
Type=Application
StartupNotify=true
Terminal=false

set-lang-controller.shのランチャー(.desktop)ファイル

[Desktop Entry]
Name=lang-control
Comment=Shortcut to controlling script
Exec=/home/yourusername/bin/set-lang-control.sh
Type=Application
StartupNotify=true
Terminal=false

スクリプトを機能させる

  1. と呼ばれるホームディレクトリにフォルダを作成しますbin。あなたはファイルマネージャーでそれを行うかmkdir $HOME/bin、ターミナルでコマンドを使用することができます
  2. binフォルダ2つのファイルを作成しますset-lang.shset-lang-control.sh。スクリプトをにset-lang.sh、コントローラースクリプトをに保存しますset-lang-control.sh。両方のスクリプトを実行可能にするsudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. 2つの.desktopファイルを作成します。1つはset-lang.desktopです。隠し.config/autostartディレクトリに配置する必要があります。2つ目はset-lang-controller.desktopbinフォルダに配置される可能性があります。次に、set-lang-controller.desktopファイルをランチャーにドラッグアンドピンします。これは、スクリプトの実行を一時的に停止および再開するためのショートカットになります。

この行Exec=は、スクリプトへのパスに実際のユーザー名が含まれるように変更する必要があることに注意してください(これが実際のホームディレクトリであるため)。たとえば、私のものはExec=/home/serg/bin/set-lang.sh

説明とカスタマイズ:

スクリプト自体は無限のwhileループで実行され、現在アクティブなウィンドウをチェックします。現在アクティブなウィンドウがケース構造のオプションの1つと一致する場合、適切な言語に切り替えます。一定の設定を回避するために、ケース構造の各部分には、言語がすでに目的の値に設定されているかどうかをチェックするifステートメントがあります。

のランチャーをダブルクリックするset-lang-controller.shと、set-lang.shスクリプトのステータスがチェックされます。スクリプトが実行中の場合-一時停止され、スクリプトが一時停止されている場合は再開されます。適切なメッセージとともに通知が表示されます。

スクリプトをカスタマイズするには、目的のアプリケーションを開いて実行wmctrl -lxし、3番目の列(ウィンドウクラス)をメモします。出力例:

$ wmctrl -lx | awk '$4="***" {print}'                                                                                                            
0x02c00007 0 gnome-terminal-server.Gnome-terminal *** Terminal
0x03a0000a 0 desktop_window.Nautilus *** Desktop
0x04a00002 0 N/A *** XdndCollectionWindowImp
0x04a00005 0 N/A *** unity-launcher
0x04a00008 0 N/A *** unity-panel
0x04a0000b 0 N/A *** unity-dash
0x04a0000c 0 N/A *** Hud
0x012000a6 0 Navigator.Firefox *** unity - Assign default keyboard language per-application - Ask Ubuntu - Mozilla Firefox

各プログラムに適切なウィンドウクラスを選択します。次に、カスタマイズを許可するスクリプトの部分に移動し、PROG_CLASSとLANGの2つのエントリを追加します。次に、ケース構造に適切なエントリを追加します。

たとえば、LibreOfficeのライターを追加したい場合は、LibreOfficeライターウィンドウを開き、ターミナルに移動してを実行しwmctrl -lxます。Writerウィンドウにclassがあることがわかりますlibreoffice.libreoffice-writer。次に私は、スクリプトに行き追加するPROG_CLASS_4=libreoffice.libreoffice-writerと、LANG4=3適切な領域インチ 一致する番号4に注意してください。次に、ケース構造に移動し、last ;;との間に次のエントリを追加しますesac

$PROG_CLASS_4) 
  if [ $CURRENT -ne  $LANG4 ];then
    gsettings set org.gnome.desktop.input-sources current $LANG4
  fi  
;;

繰り返しになりますが、$記号と一致する数字4に注目してください。

また、スクリプトが自動起動アイテムとして実行されていて、一時的に停止してカスタマイズする場合はpkill set-lang.sh、次のコマンドを使用して再開します。nohup set-lang.sh > /dev/null 2&>1 &

小さなメモ:プログラムのウィンドウクラス(ケース構造で単一の角括弧の前にあるもの)を見つける別の方法は、これxpropawkoneliner を使用することです。xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}


ありがとう、これはかなり良いスタートです。唯一の(しかし大きな)問題は、それらのアプリケーションで言語を切り替えることができないことです。スクリプトは常に私の設定を常に上書きします。これらのウィンドウでも言語を切り替えられるようにしたいと思います。それで、アプリケーションpidのチェックをいくつか追加して、言語を初めてのみまたはそのようなものに強制しますか?
grongor

また、このスクリプトはループベースではなく、イベント駆動型にすることをお勧めします。それは大したことではありませんが、これをdbusまたは何かで(可能であれば)動作させるための小さなハウツーを提供していただければ幸いです。
grongor

@GRoNGoRなので、少し考えてみましたが、今のところ、スクリプトを一時停止してでスクリプトをkill -STOP $(pgrep set-lang.sh)再開する方法はありませんkill -CONT $(pgrep set-lang.sh)。これにより、一時停止し、通常の言語に切り替えてから再開できます。
Sergiy Kolodyazhnyy 2015

たぶん、2つのコマンドにキーボードショートカットを使用するのが1つの方法かもしれないと思ったのですが、まだテストしていません。これまでのところ、理論にすぎません。十分な睡眠が取れたら、明日テストして報告します:)これが許容できるアイデアかどうか教えてください
Sergiy Kolodyazhnyy

1
素晴らしい、徹底した作業のための+1!私が言及したい2つの小さなこと:実行可能ファイル~/binはパスを必要としません($PATH再ログイン後にあるため、拡張子も必要ありません。lintian.debian.org / tags / script - with - language - extensionを参照してください).html)、停止/開始を1つの.desktopファイルに結合できます。クイックリストまたはトグル機能のいずれか。私にはかなり完璧に見えます。
Jacob Vlijm

1

あなたはそのためにインストールすることができgxneurます

sudo apt-get install gxneur

このソフトウェアはレイアウトを自動的に切り替えることができますが、それでは完璧ではありません。

しかし、手動レイアウトスイッチを設定するための非常に優れたツールがあります。

思い通りのことができます。特定のアプリケーションに特定のレイアウトを設定します。


0

以下のスクリプトは、この1つを編集したバージョンで、しばらく前に単一のアプリケーションgnome-terminal)の同様のソリューションとして投稿されました。

この質問のためにスクリプトが部分的に書き直され、複数のアプリケーションの言語を自動的に設定するために使用できるようになりました。

実際に使用する方法。アプリケーションごとに設定された言語を自動的に記憶する

スクリプトが初めて起動された場合、現在の言語はデフォルト言語であると見なされ、これは隠しファイルに記憶されています~/.lang_set

次に、使い方は簡単です。たとえばgedit、最前面のウィンドウで実行し、別の言語を設定すると、その言語は、前面でgedit再び言語を変更するまで、その後自動的に接続されますgedit

特定の言語/アプリケーションの数は、原則として無制限です。アプリケーションを実行し、アプリケーションウィンドウを前面にして言語を設定するだけです。アプリケーションは自動的に設定され、コードを編集せずに記憶されます。

イベントドリブン?

スクリプトはループで実行されますが、リソースの消費は最小限です。イベント駆動型は、イベントが最前面のウィンドウの変更であることを意味します。ループをチェックインする以外に、最前面のウィンドウを「スパイ」する以外のオプションはありません。

スクリプト

#!/usr/bin/env python3
import subprocess
import os
import time

key = [
    "org.gnome.desktop.input-sources",
    "gsettings get ", "gsettings set ",
    " sources", " current",
    ]

prev = os.environ["HOME"]+"/.lang_set"

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")

def get_front():
    # produce the frontmost application
    try:
        focus = str(hex(int(get("xdotool getwindowfocus").strip())))
        front = focus[:2]+"0"+focus[2:]
        cmd = "wmctrl -lp"
        w_list = subprocess.check_output(["/bin/bash", "-c",cmd]).decode("utf-8")
        w_match = [w for w in w_list.splitlines() if front in w][0].split()[2]
        application = get("ps -p "+w_match+" -o comm=").strip()
        # fix for 15.04, where the process name of gnome-terminal varies
        application = "gnome-terminal" if "gnome-terminal" in application else application
        return application
    except subprocess.CalledProcessError:
        return None

def get_lang():
    # get the currently running language (output = string)
    curr_n = int(get(key[1]+key[0]+key[4]).strip().split()[-1])
    return str(eval(get(key[1]+key[0]+key[3]))[curr_n])

def read_prev(application):
    # reads the possibly set languages for general and specific use (list)
    if not os.path.exists(prev):
        currlang = get_lang()
        open(prev, "wt").write("default "+currlang+"\n"+application+" "+currlang)
        return [currlang, currlang]
    else:
        return [l.strip() for l in open(prev).readlines()]

def write_changed(application, lang):
    changelist = read_prev(front_2)
    try:
        match = changelist.index([l for l in changelist if application in l][0])
        changelist[match] = application+" "+lang+"\n"
    except IndexError:
        changelist.append(application+" "+lang+"\n")
    open(prev, "wt").write(("\n").join(changelist))

def set_lang(lang):
    # set the currently used language (input = string)
    lang_i = eval(get(key[1]+key[0]+key[3])).index(eval(lang))  
    cmd = key[2]+key[0]+key[4]+" "+str(lang_i)
    subprocess.Popen(["/bin/bash", "-c", cmd])

front_1 = get_front(); lang_1 = get_lang()

while True:
    time.sleep(1)
    front_2 = get_front(); lang_2 = get_lang()
    if front_2 != None:
        if front_2 != front_1:
            try:
                setlist = read_prev(front_2)
                match = [l for l in setlist if front_2 in l][0]
            except IndexError:
                match = [l for l in setlist if "default" in l][0]
                set_lang(match[match.find(" ")+1:])            
        elif lang_2 != lang_1:
            write_changed(front_2, lang_2)
    front_1 = front_2; lang_1 = lang_2

設定方法

  1. スクリプトはとの両方xdotoolを使用しますwmctrl

    sudo apt-get install wmctrl xdotool
    
  2. 上記のスクリプトを空のファイルにコピーし、次の名前で保存します set_language.py

  3. 次のコマンドでテスト実行します。

    python3 /path/to/set_language.py
    
  4. すべてが正常に機能する場合は、スタートアップアプリケーションに追加します。スタートアップアプリケーションに追加:ダッシュ>スタートアップアプリケーション>追加。次のコマンドを追加します。

    python3 /path/to/set_language.py
    

ワンサイズですべてにフィット!+1
Fabby

こんにちは、ありがとうございました。すぐに調査し、私がどう感じているかをお知らせします:)
grongor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.