206 lines
6.1 KiB
Python
206 lines
6.1 KiB
Python
import os
|
|
import os.path
|
|
import requests
|
|
import time
|
|
from pathlib import Path
|
|
from talon import ctrl, ui, Module, Context, actions, clip
|
|
import tempfile
|
|
|
|
# Courtesy of https://github.com/anonfunc/talon-user/blob/master/apps/jetbrains.py
|
|
|
|
extendCommands = []
|
|
|
|
# Each IDE gets its own port, as otherwise you wouldn't be able
|
|
# to run two at the same time and switch between them.
|
|
# Note that MPS and IntelliJ ultimate will conflict...
|
|
port_mapping = {
|
|
"com.google.android.studio": 8652,
|
|
"com.jetbrains.AppCode": 8655,
|
|
"com.jetbrains.CLion": 8657,
|
|
"com.jetbrains.datagrip": 8664,
|
|
"com.jetbrains.goland-EAP": 8659,
|
|
"com.jetbrains.goland": 8659,
|
|
"com.jetbrains.intellij-EAP": 8653,
|
|
"com.jetbrains.intellij.ce": 8654,
|
|
"com.jetbrains.intellij": 8653,
|
|
"com.jetbrains.PhpStorm": 8662,
|
|
"com.jetbrains.pycharm": 8658,
|
|
"com.jetbrains.rider": 8660,
|
|
"com.jetbrains.rubymine": 8661,
|
|
"com.jetbrains.rubymine-EAP": 8661,
|
|
"com.jetbrains.WebStorm": 8663,
|
|
"google-android-studio": 8652,
|
|
"idea64.exe": 8653,
|
|
"IntelliJ IDEA": 8653,
|
|
"jetbrains-appcode": 8655,
|
|
"jetbrains-clion": 8657,
|
|
"jetbrains-datagrip": 8664,
|
|
"jetbrains-goland-eap": 8659,
|
|
"jetbrains-goland": 8659,
|
|
"jetbrains-idea-ce": 8654,
|
|
"jetbrains-idea-eap": 8653,
|
|
"jetbrains-idea": 8653,
|
|
"jetbrains-phpstorm": 8662,
|
|
"jetbrains-pycharm-ce": 8658,
|
|
"jetbrains-pycharm": 8658,
|
|
"jetbrains-rider": 8660,
|
|
"jetbrains-rubymine": 8661,
|
|
"jetbrains-rubymine-eap": 8661,
|
|
"jetbrains-studio": 8652,
|
|
"jetbrains-webstorm": 8663,
|
|
"RubyMine": 8661,
|
|
"RubyMine-EAP": 8661,
|
|
"PyCharm": 8658,
|
|
"pycharm64.exe": 8658,
|
|
"webstorm64.exe": 8663,
|
|
}
|
|
|
|
|
|
def _get_nonce(port, file_prefix):
|
|
file_name = file_prefix + str(port)
|
|
try:
|
|
with open(os.path.join(tempfile.gettempdir(), file_name), "r") as fh:
|
|
return fh.read()
|
|
except FileNotFoundError as e:
|
|
try:
|
|
home = str(Path.home())
|
|
with open(os.path.join(home, file_name), "r") as fh:
|
|
return fh.read()
|
|
except FileNotFoundError as eb:
|
|
print(f"Could not find {file_name} in tmp or home")
|
|
return None
|
|
except IOError as e:
|
|
print(e)
|
|
return None
|
|
|
|
|
|
def send_idea_command(cmd):
|
|
print("Sending {}".format(cmd))
|
|
active_app = ui.active_app()
|
|
bundle = active_app.bundle or active_app.name
|
|
port = port_mapping.get(bundle, None)
|
|
nonce = _get_nonce(port, ".vcidea_") or _get_nonce(port, "vcidea_")
|
|
print(f"sending {bundle} {port} {nonce}")
|
|
if port and nonce:
|
|
response = requests.get(
|
|
"http://localhost:{}/{}/{}".format(port, nonce, cmd), timeout=(0.05, 3.05)
|
|
)
|
|
response.raise_for_status()
|
|
return response.text
|
|
|
|
|
|
def get_idea_location():
|
|
return send_idea_command("location").split()
|
|
|
|
|
|
def idea_commands(commands):
|
|
command_list = commands.split(",")
|
|
print("executing jetbrains", commands)
|
|
global extendCommands
|
|
extendCommands = command_list
|
|
for cmd in command_list:
|
|
if cmd:
|
|
send_idea_command(cmd.strip())
|
|
time.sleep(0.1)
|
|
|
|
|
|
ctx = Context()
|
|
mod = Module()
|
|
|
|
mod.apps.jetbrains = "app.name: /jetbrains/"
|
|
mod.apps.jetbrains = "app.name: IntelliJ IDEA"
|
|
mod.apps.jetbrains = "app.name: PyCharm"
|
|
mod.apps.jetbrains = "app.name: RubyMine"
|
|
mod.apps.jetbrains = "app.name: RubyMine-EAP"
|
|
|
|
# windows
|
|
mod.apps.jetbrains = "app.name: idea64.exe"
|
|
mod.apps.jetbrains = "app.name: PyCharm64.exe"
|
|
mod.apps.jetbrains = "app.name: pycharm64.exe"
|
|
mod.apps.jetbrains = "app.name: webstorm64.exe"
|
|
mod.apps.jetbrains = """
|
|
os: mac
|
|
and app.bundle: com.jetbrains.pycharm
|
|
"""
|
|
|
|
|
|
@mod.action_class
|
|
class Actions:
|
|
def idea(commands: str):
|
|
"""Send a command to Jetbrains product"""
|
|
idea_commands(commands)
|
|
|
|
def idea_grab(times: int):
|
|
"""Copies specified number of words to the left"""
|
|
old_clip = clip.get()
|
|
try:
|
|
original_line, original_column = get_idea_location()
|
|
for _ in range(times):
|
|
send_idea_command("action EditorSelectWord")
|
|
send_idea_command("action EditorCopy")
|
|
send_idea_command("goto {} {}".format(original_line, original_column))
|
|
send_idea_command("action EditorPaste")
|
|
finally:
|
|
clip.set(old_clip)
|
|
global extendCommands
|
|
extendCommands = []
|
|
|
|
|
|
ctx.matches = r"""
|
|
app: jetbrains
|
|
"""
|
|
|
|
|
|
@ctx.action_class("win")
|
|
class win_actions:
|
|
def filename():
|
|
title = actions.win.title()
|
|
result = title.split(" ")
|
|
|
|
for word in result:
|
|
if "." in word:
|
|
return word
|
|
|
|
return ""
|
|
|
|
@ctx.action_class("edit")
|
|
class edit_actions:
|
|
def jump_line(n: int):
|
|
actions.user.idea("goto {} 0".format(n))
|
|
# move the cursor to the first nonwhite space character of the line
|
|
actions.user.idea("action EditorLineEnd")
|
|
actions.user.idea("action EditorLineStart")
|
|
|
|
|
|
@ctx.action_class("user")
|
|
class user_actions:
|
|
def tab_jump(number: int):
|
|
# depends on plugin GoToTabs
|
|
if number < 10:
|
|
actions.user.idea("action GoToTab{}".format(number))
|
|
|
|
def extend_until_line(line: int):
|
|
actions.user.idea("extend {}".format(line))
|
|
|
|
def select_range(line_start: int, line_end: int):
|
|
# if it's a single line, select the entire thing including the ending new-line5
|
|
if line_start == line_end:
|
|
actions.user.idea("goto {} 0".format(line_start))
|
|
actions.user.idea("action EditorSelectLine"),
|
|
else:
|
|
actions.user.idea("range {} {}".format(line_start, line_end))
|
|
|
|
def extend_camel_left():
|
|
actions.user.idea("action EditorPreviousWordInDifferentHumpsModeWithSelection")
|
|
|
|
def extend_camel_right():
|
|
actions.user.idea("action EditorNextWordInDifferentHumpsModeWithSelection")
|
|
|
|
def camel_left():
|
|
actions.user.idea("action EditorPreviousWordInDifferentHumpsMode")
|
|
|
|
def camel_right():
|
|
actions.user.idea("action EditorNextWordInDifferentHumpsMode")
|
|
|
|
def line_clone(line: int):
|
|
actions.user.idea("clone {}".format(line))
|