Skip to content

Commit

Permalink
Merge pull request SublimeText#610 from ig0774/keep_focus
Browse files Browse the repository at this point in the history
Keep focus for Windows and Linux
  • Loading branch information
msiniscalchi committed Dec 8, 2015
2 parents 89ee70a + 9f9a28d commit 7bcd595
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 36 deletions.
20 changes: 18 additions & 2 deletions LaTeXTools.default-settings
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"fill_auto_trigger": true,

// Keep focus on Sublime Text after building (true) or switch to PDF viewer (false)
// If you are on Windows or Linux and using ST2, you may need to set the
// "sublime_executable" setting for this to work in your platform settings.
"keep_focus": true,
// Sync PDF to current editor position after building (true) or not
"forward_sync": true,
Expand Down Expand Up @@ -92,7 +94,14 @@
// TeX distro: "miktex" or "texlive"
"distro" : "miktex",
// Command to invoke Sumatra. If blank, "SumatraPDF.exe" is used (it has to be on your PATH)
"sumatra": ""
"sumatra": "",
// Command to invoke Sublime Text. Used if the keep_focus toggle is true.
// If blank, "subl.exe" or "sublime_text.exe" will be used.
"sublime_executable": "",
// how long (in seconds) to wait after the jump_to_pdf command completes
// before switching focus back to Sublime Text. This may need to be
// adjusted depending on your machine and configuration.
"keep_focus_delay": 0.5
},

"linux" : {
Expand All @@ -110,7 +119,14 @@
// Note: only tweak this if sync after launching the PDF viewer does not seem to work,
// or if the PDF viewer opens instantly and you don't want to wait.
// Default: 1.5 (works on my MBP4,1...)
"sync_wait": 1.5
"sync_wait": 1.5,
// Command to invoke Sublime Text. Used if the keep_focus toggle is true.
// If blank, "subl" or "sublime_text" will be used.
"sublime_executable": "",
// how long (in ms) to wait after the jump_to_pdf command completes
// before switching focus back to Sublime Text. This may need to be
// adjusted depending on your machine and configuration.
"keep_focus_delay": 0.5
},

// ------------------------------------------------------------------
Expand Down
6 changes: 5 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ The following options are currently available (defaults in parentheses):
- `fill_auto_trigger` (`true`): ditto, but for package and file inclusion commands (see Fill Helper feature above)
- `cwl_completion` (`prefixed`): when to activate the cwl completion poput (see LaTeX-cwl feature above)
- `cwl_list` (empty): list of paths to cwl files
- `keep_focus` (`true`): if `true`, after compiling a tex file, ST retains the focus; if `false`, the PDF viewer gets the focus. Also note that you can *temporarily* toggle this behavior with `C-l,t,f`.
- `keep_focus` (`true`): if `true`, after compiling a tex file, ST retains the focus; if `false`, the PDF viewer gets the focus. Also note that you can *temporarily* toggle this behavior with `C-l,t,f`. **Note**: If you are on either Windows or Linux you may need to adjust the `sublime_executable` setting for this to work properly. See the **Platform settings** below.
- `forward_sync` (`true`): if `true`, after compiling a tex file, the PDF viewer is asked to sync to the position corresponding to the current cursor location in ST. You can also *temporarily* toggle this behavior with `C-l,t,s`.
- `temp_files_exts`: list of file extensions to be considered temporary, and hence deleted using the `C-l, backspace` command.
- `temp_files_ignored_folders`: subdirectories to skip when deleting temp files.
Expand All @@ -410,10 +410,14 @@ The following options are currently available (defaults in parentheses):
- `windows`-specific settings:
* `distro`: either `miktex` or `texlive`, depending on your TeX distribution
* `sumatra`: leave blank or omit if the SumatraPDF executable is in your `PATH` and is called `SumatraPDF.exe`, as in a default installation; otherwise, specify the *full path and file name* of the SumatraPDF executable.
* `sublime_executable`: this is used if `keep_focus` is set to true and the path to your sublime_text executable cannot be discovered automatically. It should point to the full path to your executable `sublime_text.exe`.
* `keep_focus_delay`: this is used if `keep_focus` is set to true. It controls how long (in seconds) the delay is between the completion of the `jump_to_pdf` command and the attempt to refocus on Sublime Text. This may need to be adjusted depending on your machine or configuration.
- `linux`-specific settings:
* `python2` (`""`, i.e. empty string): name of the Python 2 executable. This is useful for systems that ship with both Python 2 and Python 3. The forward/backward search used with Evince require Python 2.
* `sublime` (`sublime-text`): name of the ST executable. Ubuntu supports both `sublime-text` and `subl`; other distros may vary.
* `sync_wait` (1.5): when you ask LaTeXTools to do a forward search, and the PDF file is not yet open (for example, right after compiling a tex file for the first time), LaTeXTools first launches evince, then waits a bit for it to come up, and then it performs the forward search. This parameter controls how long LaTeXTools should wait. If you notice that your machine opens the PDF, then sits there doing nothing, and finally performs the search, you can decrease this value to 1.0 or 0.5; if instead the PDF file comes up but the forward search does not seem to happen, increase it to 2.0.
* `sublime_executable`: this is used if `keep_focus` is set to true and the path to your sublime_text executable cannot be discovered automatically. It should point to the full path to your executable `sublime_text`.
* `keep_focus_delay`: this is used if `keep_focus` is set to true. It controls how long (in seconds) the delay is between the completion of the `jump_to_pdf` command and the attempt to refocus on Sublime Text. This may need to be adjusted depending on your machine or configuration.

**Build engine settings**:

Expand Down
176 changes: 143 additions & 33 deletions jumpToPDF.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ST2/ST3 compat
from __future__ import print_function
import sublime
import sys
if sublime.version() < '3000':
# we are on ST2 and Python 2.X
_ST3 = False
Expand All @@ -13,11 +14,146 @@


import sublime_plugin, os.path, subprocess, time
import re

SUBLIME_VERSION = re.compile(r'Build (\d{4})', re.UNICODE)

# attempts to locate the sublime executable to refocus on ST if keep_focus
# is set.
def get_sublime_executable():
processes = ['subl', 'sublime_text']

def check_processes(st2_dir=None):
if st2_dir is None or os.path.exists(st2_dir):
for process in processes:
try:
if st2_dir is not None:
process = os.path.join(st2_dir, process)

p = subprocess.Popen(
[process, '-v'],
stdout=subprocess.PIPE,
startupinfo=startupinfo,
shell=shell,
env=os.environ
)
except:
pass
else:
stdout, _ = p.communicate()

if p.returncode == 0:
m = SUBLIME_VERSION.search(stdout.decode('utf8'))
if m and m.group(1) == version:
return process
return None

s = sublime.load_settings('LaTeXTools.sublime-settings')
plat_settings = s.get(sublime.platform(), {})
sublime_executable = plat_settings.get('sublime_executable', None)

if sublime_executable:
return sublime_executable

# we cache the results of the other checks, if possible
if hasattr(get_sublime_executable, 'result'):
return get_sublime_executable.result

# are we on ST3
if hasattr(sublime, 'executable_path'):
get_sublime_executable.result = sublime.executable_path()
return get_sublime_executable.result
# in ST2 the Python executable is actually "sublime_text"
elif sys.executable != 'python' and os.path.isabs(sys.executable):
get_sublime_executable.result = sys.executable
return get_sublime_executable.result

# guess-work for ST2
startupinfo = None
shell = False
if sublime.platform() == 'windows':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
shell = _ST3

version = sublime.version()

result = check_processes()
if result is not None:
get_sublime_executable.result = result
return result

platform = sublime.platform()

# guess the default install location for ST2 on Windows
if platform == 'windows':
st2_dir = os.path.expandvars("%PROGRAMFILES%\\Sublime Text 2")
result = check_processes(st2_dir)
if result is not None:
get_sublime_executable.result = result
return result
# guess some locations for ST2 on Linux
elif platform == 'linux':
for path in [
'$HOME/bin',
'$HOME/sublime_text_2',
'$HOME/sublime_text',
'/opt/sublime_text_2',
'/opt/sublime_text',
'/usr/local/bin',
'/usr/bin'
]:
st2_dir = os.path.expandvars(path)
result = check_processes(st2_dir)
if result is not None:
get_sublime_executable.result = result
return result

get_sublime_executable.result = None

sublime.status_message(
'Cannot determine the path to your Sublime installation. Please ' +
'set the "sublime_executable" setting in your LaTeXTools.sublime-settings ' +
'file.'
)

return None


# Jump to current line in PDF file
# NOTE: must be called with {"from_keybinding": <boolean>} as arg

class jump_to_pdfCommand(sublime_plugin.TextCommand):

def focus_st(self):
sublime_command = get_sublime_executable()

if sublime_command is not None:
s = sublime.load_settings('LaTeXTools.sublime-settings')
platform = sublime.platform()
plat_settings = s.get(platform, {})
wait_time = plat_settings.get('keep_focus_delay', 0.5)

def keep_focus():
startupinfo = None
shell = False
if platform == 'windows':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
shell = _ST3

subprocess.Popen(
sublime_command,
startupinfo=startupinfo,
shell=shell,
env=os.environ
)

if hasattr(sublime, 'set_async_timeout'):
sublime.set_async_timeout(keep_focus, int(wait_time * 1000))
else:
sublime.set_timeout(keep_focus, int(wait_time * 1000))

def run(self, edit, **args):
# Check prefs for PDF focus and sync
s = sublime.load_settings("LaTeXTools.sublime-settings")
Expand Down Expand Up @@ -78,37 +214,13 @@ def run(self, edit, **args):
elif plat == 'win32':
# determine if Sumatra is running, launch it if not
print ("Windows, Calling Sumatra")
# hide console
# NO LONGER NEEDED with new Sumatra?
# startupinfo = subprocess.STARTUPINFO()
# startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
# tasks = subprocess.Popen(["tasklist"], stdout=subprocess.PIPE,
# startupinfo=startupinfo).communicate()[0]
# # Popen returns a byte stream, i.e. a single line. So test simply:
# # Wait! ST3 is stricter. We MUST convert to str
# tasks_str = tasks.decode('UTF-8') #guess..
# if "SumatraPDF.exe" not in tasks_str:
# print ("Sumatra not running, launch it")
# self.view.window().run_command("view_pdf")
# time.sleep(0.5) # wait 1/2 seconds so Sumatra comes up
setfocus = 0 if keep_focus else 1
# First send an open command forcing reload, or ForwardSearch won't
# reload if the file is on a network share
# command = u'[Open(\"%s\",0,%d,1)]' % (pdffile,setfocus)
# print (repr(command))
# self.view.run_command("send_dde",
# { "service": "SUMATRA", "topic": "control", "command": command})
# Now send ForwardSearch command if needed

si = subprocess.STARTUPINFO()
if setfocus == 0:
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = 4 #constant for SHOWNOACTIVATE
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = 4 #constant for SHOWNOACTIVATE

# If the option doesn't exist, return "SumatraPDF.exe"; else return the option
# And, if the option is "", use "SumatraPDF.exe"
su_binary = prefs_win.get("sumatra", "SumatraPDF.exe") or 'SumatraPDF.exe'
startCommands = [su_binary,"-reuse-instance"]
startCommands = [su_binary, "-reuse-instance"]
if forward_sync:
startCommands.append("-forward-search")
startCommands.append(srcfile)
Expand All @@ -117,13 +229,9 @@ def run(self, edit, **args):
startCommands.append(pdffile)

subprocess.Popen(startCommands, startupinfo = si)
# command = "[ForwardSearch(\"%s\",\"%s\",%d,%d,0,%d)]" \
# % (pdffile, srcfile, line, col, setfocus)
# print (command)
# self.view.run_command("send_dde",
# { "service": "SUMATRA", "topic": "control", "command": command})


if keep_focus:
self.focus_st()
elif 'linux' in plat: # for some reason, I get 'linux2' from sys.platform
print ("Linux!")

Expand Down Expand Up @@ -157,5 +265,7 @@ def run(self, edit, **args):
time.sleep(sync_wait)
if forward_sync:
subprocess.Popen([py_binary, ev_fwd_exec, pdffile, str(line), srcfile])
if keep_focus:
self.focus_st()
else: # ???
pass

0 comments on commit 7bcd595

Please sign in to comment.