mirror of
https://github.com/sstent/sublime-text-3.git
synced 2026-01-26 07:01:47 +00:00
backing up sublime settings
This commit is contained in:
183
Packages/SublimeREPL/text_transfer.py
Normal file
183
Packages/SublimeREPL/text_transfer.py
Normal file
@@ -0,0 +1,183 @@
|
||||
from __future__ import absolute_import, unicode_literals, print_function, division
|
||||
|
||||
import re
|
||||
import sublime_plugin
|
||||
import sublime
|
||||
from collections import defaultdict
|
||||
import tempfile
|
||||
import binascii
|
||||
|
||||
try:
|
||||
from .sublimerepl import manager, SETTINGS_FILE
|
||||
except (ImportError, ValueError):
|
||||
from sublimerepl import manager, SETTINGS_FILE
|
||||
|
||||
|
||||
def default_sender(repl, text, view=None):
|
||||
repl.write(text)
|
||||
|
||||
"""Senders is a dict of functions used to transfer text to repl as a repl
|
||||
specific load_file action"""
|
||||
SENDERS = defaultdict(lambda: default_sender)
|
||||
|
||||
|
||||
def sender(external_id,):
|
||||
def wrap(func):
|
||||
SENDERS[external_id] = func
|
||||
return wrap
|
||||
|
||||
|
||||
@sender("coffee")
|
||||
def coffee(repl, text, view=None):
|
||||
"""
|
||||
use CoffeeScript multiline hack
|
||||
http://coffeescript.org/documentation/docs/repl.html
|
||||
"""
|
||||
default_sender(repl, text.replace("\n", u'\uFF00') + "\n", view)
|
||||
|
||||
@sender("python")
|
||||
def python_sender(repl, text, view=None):
|
||||
text_wo_encoding = re.sub(
|
||||
pattern=r"#.*coding[:=]\s*([-\w.]+)",
|
||||
repl="# <SublimeREPL: encoding comment removed>",
|
||||
string=text,
|
||||
count=1)
|
||||
code = binascii.hexlify(text_wo_encoding.encode("utf-8"))
|
||||
execute = ''.join([
|
||||
'from binascii import unhexlify as __un; exec(compile(__un("',
|
||||
str(code.decode('ascii')),
|
||||
'").decode("utf-8"), "<string>", "exec"))\n'
|
||||
])
|
||||
return default_sender(repl, execute, view)
|
||||
|
||||
|
||||
@sender("ruby")
|
||||
def ruby_sender(repl, text, view=None):
|
||||
code = binascii.b2a_base64(text.encode("utf-8"))
|
||||
payload = "begin require 'base64'; eval(Base64.decode64('%s'), binding=TOPLEVEL_BINDING) end\n" % (code.decode("ascii"),)
|
||||
return default_sender(repl, payload, view)
|
||||
|
||||
|
||||
# custom clojure sender that makes sure that all selections are
|
||||
# evaluated in the namespace declared by the file they are in
|
||||
@sender("clojure")
|
||||
def clojure_sender(repl, text, view):
|
||||
# call (load-string) instead of just writing the string so
|
||||
# that syntax errors are caught and thrown back immediately
|
||||
text = '(load-string "' + text.strip().replace('"', r'\"') + '")'
|
||||
|
||||
# find the first non-commented statement from the start of the file
|
||||
namespacedecl = view.find(r"^[^;]*?\(", 0)
|
||||
|
||||
# if it's a namespace declaration, go search for the namespace name
|
||||
if namespacedecl and view.scope_name(namespacedecl.end()-1).startswith("source.clojure meta.function.namespace.clojure"):
|
||||
namespacedecl = view.extract_scope(namespacedecl.end()-1)
|
||||
|
||||
# we're looking for the first symbol within the declaration that
|
||||
# looks like a namespace and isn't metadata, a comment, etc.
|
||||
pos = namespacedecl.begin() + 3
|
||||
while pos < namespacedecl.end():
|
||||
# see http://clojure.org/reader for a description of valid
|
||||
# namespace names. the inital } or whitespace make sure we're
|
||||
# not matching on keywords etc.
|
||||
namespace = view.find(r"[\}\s][A-Za-z\_!\?\*\+\-][\w!\?\*\+\-:]*(\.[\w!\?\*\+\-:]+)*", pos)
|
||||
|
||||
if not namespace:
|
||||
# couldn't find the namespace name within the declaration. suspicious.
|
||||
break
|
||||
elif view.scope_name(namespace.begin() + 1).startswith("source.clojure meta.function.namespace.clojure entity.name.namespace.clojure"):
|
||||
# looks alright, we've got our namespace!
|
||||
# switch to namespace before executing command
|
||||
|
||||
# we could do this explicitly by calling (ns), (in-ns) etc:
|
||||
# text = "(ns " + view.substr(namespace)[1:] + ") " + text
|
||||
# but this would not only result in an extra return value
|
||||
# printed to the user, the repl would also remain in that
|
||||
# namespace after execution, so instead we do the same thing
|
||||
# that swank-clojure does:
|
||||
text = "(binding [*ns* (or (find-ns '" + view.substr(namespace)[1:] + ") (find-ns 'user))] " + text + ')'
|
||||
# i.e. we temporarily switch to the namespace if it has already
|
||||
# been created, otherwise we execute it in 'user. the most
|
||||
# elegant option for this would probably be:
|
||||
# text = "(binding [*ns* (create-ns '" + view.substr(namespace)[1:] + ")] " + text + ')'
|
||||
# but this can lead to problems because of newly created
|
||||
# namespaces not automatically referring to clojure.core
|
||||
# (see https://groups.google.com/forum/?fromgroups=#!topic/clojure/Th-Bqq68hfo)
|
||||
break
|
||||
else:
|
||||
# false alarm (metadata or a comment), keep looking
|
||||
pos = namespace.end()
|
||||
return default_sender(repl, text + repl.cmd_postfix, view)
|
||||
|
||||
class ReplViewWrite(sublime_plugin.TextCommand):
|
||||
def run(self, edit, external_id, text):
|
||||
for rv in manager.find_repl(external_id):
|
||||
rv.append_input_text(text)
|
||||
break # send to first repl found
|
||||
else:
|
||||
sublime.error_message("Cannot find REPL for '{0}'".format(external_id))
|
||||
|
||||
|
||||
class ReplSend(sublime_plugin.TextCommand):
|
||||
def run(self, edit, external_id, text, with_auto_postfix=True):
|
||||
for rv in manager.find_repl(external_id):
|
||||
if with_auto_postfix:
|
||||
text += rv.repl.cmd_postfix
|
||||
if sublime.load_settings(SETTINGS_FILE).get('show_transferred_text'):
|
||||
rv.append_input_text(text)
|
||||
rv.adjust_end()
|
||||
SENDERS[external_id](rv.repl, text, self.view)
|
||||
break
|
||||
else:
|
||||
sublime.error_message("Cannot find REPL for '{}'".format(external_id))
|
||||
|
||||
|
||||
class ReplTransferCurrent(sublime_plugin.TextCommand):
|
||||
def run(self, edit, scope="selection", action="send"):
|
||||
text = ""
|
||||
if scope == "selection":
|
||||
text = self.selected_text()
|
||||
elif scope == "lines":
|
||||
text = self.selected_lines()
|
||||
elif scope == "function":
|
||||
text = self.selected_functions()
|
||||
elif scope == "block":
|
||||
text = self.selected_blocks()
|
||||
elif scope == "file":
|
||||
text = self.selected_file()
|
||||
cmd = "repl_" + action
|
||||
self.view.window().run_command(cmd, {"external_id": self.repl_external_id(), "text": text})
|
||||
|
||||
def repl_external_id(self):
|
||||
return self.view.scope_name(0).split(" ")[0].split(".", 1)[1]
|
||||
|
||||
def selected_text(self):
|
||||
v = self.view
|
||||
parts = [v.substr(region) for region in v.sel()]
|
||||
return "".join(parts)
|
||||
|
||||
def selected_blocks(self):
|
||||
# TODO: Clojure only for now
|
||||
v = self.view
|
||||
strs = []
|
||||
old_sel = list(v.sel())
|
||||
v.run_command("expand_selection", {"to": "brackets"})
|
||||
v.run_command("expand_selection", {"to": "brackets"})
|
||||
for s in v.sel():
|
||||
strs.append(v.substr(s))
|
||||
v.sel().clear()
|
||||
for s in old_sel:
|
||||
v.sel().add(s)
|
||||
return "\n\n".join(strs)
|
||||
|
||||
def selected_lines(self):
|
||||
v = self.view
|
||||
parts = []
|
||||
for sel in v.sel():
|
||||
for line in v.lines(sel):
|
||||
parts.append(v.substr(line))
|
||||
return "\n".join(parts)
|
||||
|
||||
def selected_file(self):
|
||||
v = self.view
|
||||
return v.substr(sublime.Region(0, v.size()))
|
||||
Reference in New Issue
Block a user