Weisen Sie pro Anwendung die Standardtastatursprache zu

11

Ist es möglich, für bestimmte Anwendungen eine Standardtastatursprache zuzuweisen? Ich weiß, dass es eine Option gibt, eine Anwendung immer mit einer Standardtastatursprache zu starten, aber das ist nicht das, was ich will.

Ich suche etwas Ähnliches wie "feste Arbeitsbereiche", die Sie mit CompizConfig festlegen können (Sie stellen Chrome so ein, dass es immer bei X1Y1, Terminal bei X2Y1 usw. geöffnet ist). Etwas, wo ich Chrome einstellen würde: Tschechisch, Terminal: Englisch, Spotify: Englisch, ...

grongor
quelle
In "Texteingabe" gibt es die Option "Unterschiedliche Quellen für jedes Fenster zulassen". Möglicherweise ein Schritt in die richtige Richtung für Sie.
Gunnar Hjalmarsson
Ja, danke, das weiß ich. Dies ist der notwendige Schritt, den ich sagen würde, aber leider nicht das, was ich erreichen möchte. Danke trotzdem.
Grongor
Es gibt einen Skriptweg. Sie brauchen nur diese 3 Apps oder es gibt andere? Je nachdem, wie flexibel das Skript sein soll, kann es mehr oder weniger dauern, bis ich es schreibe
Sergiy Kolodyazhnyy
@ JacobVlijm Klingt nach einem weiteren guten Job für Python;)
Sergiy Kolodyazhnyy
Hat eine Antwort gepostet. Lassen Sie mich wissen, was Sie denken
Sergiy Kolodyazhnyy

Antworten:

6

Einführung

Das folgende Skript legt die Sprache für jedes benutzerdefinierte Programm entsprechend der Position dieser Sprache im Sprachmenü fest. Wenn meine Bestellung beispielsweise Englisch (1), Chinesisch (2) und Russisch (3) lautet, kann ich Firefox auf Sprache 2, Terminal auf Sprache 1 und LibreOffice auf Sprache 3 einstellen.

Das Skript besteht aus zwei Teilen: Teil eins ist das eigentliche Skript, das die Arbeit erledigt, das zweite Skript dient als Steuerelement. Die Idee ist , die Spracheinstellung Skript als laufen Start-up - Anwendung und wann immer Sie manuell ändern Sprache benötigen - Mit Doppelklick auf die Verknüpfung zu dem Controller Skript.

Voraussetzungen

  1. Installieren Sie das wmctrlProgramm mit sudo apt-get install wmctrl.

Skript

#!/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

Controller-Skript

#!/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 

Launcher-Datei (.desktop) für das Skript set-lang.sh

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

Launcher-Datei (.desktop) für set-lang-controller.sh

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

Damit das Skript funktioniert

  1. Erstellen Sie einen Ordner in Ihrem Home-Verzeichnis mit dem Namen bin. Sie können dies im Dateimanager tun oder den Befehl mkdir $HOME/binim Terminal verwenden
  2. binErstellen Sie im Ordner zwei Dateien: set-lang.shund set-lang-control.sh. Speichern Sie das Skript in set-lang.shund das Controller-Skript in set-lang-control.sh. Machen Sie beide Skripte ausführbar mitsudo chmod +x $HOME/bin/set-lang-control.sh $HOME/bin/set-lang.sh
  3. Erstellen Sie zwei .desktopDateien. Eins ist set-lang.desktop. Muss im versteckten .config/autostartVerzeichnis abgelegt werden . Zweitens ist set-lang-controller.desktop, kann in Ihrem binOrdner platziert werden. Ziehen Sie anschließend die set-lang-controller.desktopDatei per Drag & Pin an den Launcher . Dies wird zur Verknüpfung zum vorübergehenden Stoppen und Fortsetzen der Skriptausführung.

HINWEIS : Die Zeile Exec=muss geändert werden, damit Ihr tatsächlicher Benutzername im Pfad zum Skript enthalten ist (da dies Ihr tatsächliches Ausgangsverzeichnis ist). Zum Beispiel wäre meineExec=/home/serg/bin/set-lang.sh

Erklärung und Anpassung:

Das Skript selbst wird in einer Endlosschleife ausgeführt und überprüft das aktuell aktive Fenster. Wenn das aktuell aktive Fenster mit einer der Optionen in der Fallstruktur übereinstimmt, wechseln wir zur entsprechenden Sprache. Um eine konstante Einstellung zu vermeiden, verfügt jeder Teil der Fallstruktur über eine if-Anweisung, die prüft, ob die Sprache bereits auf den gewünschten Wert eingestellt wurde.

Durch Doppelklicken auf den Launcher für set-lang-controller.shwird der Status des set-lang.shSkripts überprüft . Wenn das Skript ausgeführt wird, wird es angehalten, und wenn das Skript angehalten wird, wird es fortgesetzt. Eine Benachrichtigung wird mit der entsprechenden Nachricht angezeigt.

Um das Skript anzupassen, können Sie die gewünschten Anwendungen öffnen wmctrl -lx, die dritte Spalte ausführen und notieren - die Fensterklasse. Beispielausgabe:

$ 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

Wählen Sie für jedes Programm die entsprechenden Fensterklassen aus. Wechseln Sie als Nächstes zu dem Teil des Skripts, der die Anpassung ermöglicht, und fügen Sie zwei Einträge für PROG_CLASS und LANG hinzu. Fügen Sie als Nächstes den entsprechenden Eintrag in die Fallstruktur ein.

Wenn ich beispielsweise LibreOffice's Writer hinzufügen möchte, öffne ich das LibreOffice Writer-Fenster, gehe zum Terminal und führe es aus wmctrl -lx. Es wird mir sagen, dass das Writer-Fenster Klasse hat libreoffice.libreoffice-writer. Als nächstes gehe ich zum Skript, füge hinzu PROG_CLASS_4=libreoffice.libreoffice-writerund LANG4=3in den entsprechenden Bereich. Beachten Sie die übereinstimmende Nummer 4. Wechseln Sie als Nächstes zur Fallstruktur und fügen Sie den folgenden Eintrag zwischen last ;;und hinzu esac:

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

Beachten Sie erneut das $ -Zeichen und die übereinstimmende Nummer 4.

Wenn das Skript als Autostart-Element ausgeführt wird und Sie es vorübergehend anhalten möchten, um es anzupassen, verwenden Sie es pkill set-lang.shund fahren Sie mit fortnohup set-lang.sh > /dev/null 2&>1 &

Kleiner Hinweis: Eine andere Möglichkeit, die Fensterklasse für ein Programm herauszufinden (das Zeug, das in der Fallstruktur vor einer einzelnen runden Klammer steht), besteht darin, dies xpropund einen awkOneliner zu verwenden:xprop | awk '/WM_CLASS/ {gsub(/"/," "); print $3"."$5}

Sergiy Kolodyazhnyy
quelle
Danke, das ist ein ziemlich guter Anfang. Das einzige (aber große) Problem ist, dass ich die Sprache in diesen Anwendungen nicht wechseln kann. Das Skript überschreibt einfach ständig meine Einstellungen. Ich möchte auch in diesen Fenstern die Sprache wechseln können. Fügen Sie also vielleicht erst beim ersten Mal eine Überprüfung auf Anwendungs-PID und Force-Sprache hinzu oder so etwas?
Grongor
Ich würde es auch vorziehen, wenn dieses Skript ereignisgesteuert und nicht schleifenbasiert wäre. Es ist keine große Sache, aber ich würde mich sehr freuen, wenn Sie eine kleine Anleitung bereitstellen könnten, um dies mit dbus oder etwas anderem zum Laufen zu bringen (wenn es möglich ist).
Grongor
@GRoNGoR, also habe ich ein bisschen darüber nachgedacht, und bis jetzt sehe ich keine Möglichkeit, das Skript anzuhalten, außer kill -STOP $(pgrep set-lang.sh)und setze das Skript dann mit fort kill -CONT $(pgrep set-lang.sh). Auf diese Weise können Sie es anhalten, die Sprache normal wechseln und dann fortfahren.
Sergiy Kolodyazhnyy
Ein kurzer Gedanke, den ich hatte, ist, dass vielleicht die Verwendung einer Tastenkombination für die beiden Befehle der Weg ist, dies zu tun, aber ich habe es noch nicht getestet, nur eine Theorie bisher. Werde morgen testen, sobald ich genug Schlaf habe und mich wieder melde :) Lass es mich wissen, wenn dies eine akzeptable Idee wäre
Sergiy Kolodyazhnyy
1
+1 für die tolle und gründliche Arbeit! Zwei winzige Dinge, die ich erwähnen möchte: Ausführbare Dateien in ~/binbenötigen weder den Pfad (noch die Erweiterung, da sie $PATHnach einer erneuten Anmeldung vorhanden sind, siehe: lintian.debian.org/tags/script-with-language-extension .html ), und Sie können Stop / Start in einer .desktopDatei kombinieren ; entweder in einer Quicklist oder einer Umschaltfunktion. sieht für mich ziemlich perfekt aus.
Jacob Vlijm
1

Sie können dies installieren gxneur, indem Sie ausführen

sudo apt-get install gxneur

Diese Software kann Layouts automatisch wechseln, ist aber damit nicht perfekt.

Aber es hat sehr schöne Werkzeuge, um manuelle Layout-Schalter einzurichten.

Sie können genau das tun, was Sie wollen. Festlegen bestimmter Layouts für bestimmte Anwendungen.

Pilot6
quelle
0

Das folgende Skript ist eine bearbeitete Version dieses Skripts , die vor einiger Zeit als ähnliche Lösung für eine einzelne Anwendung ( gnome-terminal) veröffentlicht wurde.

Das Skript wurde für diese Frage teilweise neu geschrieben, um damit automatisch Sprachen für mehrere Anwendungen festlegen zu können.

Wie in der Praxis zu verwenden; merkt sich automatisch die eingestellte Sprache pro Anwendung

Wenn das Skript zum ersten Mal gestartet wird, wird angenommen, dass die aktuelle Sprache die Standardsprache ist, die in einer versteckten Datei gespeichert wird : ~/.lang_set.

Dann ist die Verwendung einfach: Wenn Sie z. B. geditim vordersten Fenster ausführen und eine andere Sprache einstellen, wird diese Sprache geditvon da an automatisch verbunden , bis Sie die Sprache mit geditvorne wieder ändern .

Die Anzahl der spezifischen Sprachen / Anwendungen ist grundsätzlich unbegrenzt; Führen Sie einfach die Anwendung aus und stellen Sie die Sprache mit dem Anwendungsfenster vor. Die Anwendung wird automatisch festgelegt und gespeichert, ohne den Code zu bearbeiten.

Ereignisgesteuert?

Obwohl das Skript in einer Schleife ausgeführt wird, ist der Ressourcenverbrauch minimal. Ereignisgesteuert würde bedeuten, dass das Ereignis eine Änderung im vordersten Fenster ist. Ich sehe keine andere Möglichkeit, als das vorderste Fenster auszuspionieren, als in einer Schleife einzuchecken.

Das Skript

#!/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

Wie stellt man das ein

  1. Das Skript verwendet beide xdotoolund wmctrl:

    sudo apt-get install wmctrl xdotool
    
  2. Kopieren Sie das obige Skript in eine leere Datei und speichern Sie es unter set_language.py

  3. Testen Sie es mit dem folgenden Befehl:

    python3 /path/to/set_language.py
    
  4. Wenn alles wie erwartet funktioniert, fügen Sie es zu Startanwendungen hinzu: Zu Startanwendungen hinzufügen: Dash> Startanwendungen> Hinzufügen. Fügen Sie den Befehl hinzu:

    python3 /path/to/set_language.py
    
Jacob Vlijm
quelle
Eine Grösse passt allen! +1
Fabby
Hey, vielen Dank dafür, ich werde es bald untersuchen und dich wissen lassen, wie ich mich dabei fühle :)
Grongor