├── foo.html ├── repllibs └── __init__.py ├── .no-sublime-package ├── .gitignore ├── .hgignore ├── messages.json ├── __init__.py ├── doc ├── _static │ ├── menu.png │ └── palette.png ├── make.bat ├── Makefile └── conf.py ├── config ├── OCaml │ ├── OCaml (toplevel).sublime-settings │ ├── Default.sublime-commands │ ├── OCaml (toplevel).tmLanguage │ └── Main.sublime-menu ├── F │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── R │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Perl │ ├── re.pl │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Io │ ├── Default.sublime-commands │ ├── Main.sublime-menu │ ├── repl.io │ └── Io.tmLanguage ├── Lua │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── PHP │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── SML │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── GDB │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── NodeJS │ ├── Default.sublime-commands │ ├── Main.sublime-menu │ └── repl.js ├── Shell │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Elixir │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Erlang │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Groovy │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Matlab │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Octave │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Rails │ ├── Default.sublime-commands │ ├── Main.sublime-menu │ └── pry_repl.rb ├── Haskell │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Maxima │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── MozRepl │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Racket │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Tower │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── ScriptCS │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── PowerShell │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Prolog │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Execnet │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── CoffeeScript │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Sublime │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Clojure │ ├── Default.sublime-keymap │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Scala │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Ruby │ ├── Default.sublime-commands │ ├── pry_repl.rb │ └── Main.sublime-menu ├── ClojureScript │ ├── Default.sublime-commands │ ├── clojurescript.tmLanguage │ └── Main.sublime-menu ├── Scheme │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Main.sublime-menu.template ├── Python │ ├── Default.sublime-commands │ ├── ipy_repl.py │ └── Main.sublime-menu └── CommonLisp │ ├── Default.sublime-commands │ └── Main.sublime-menu ├── Default.sublime-commands ├── SublimeREPL (OSX).sublime-settings ├── repls ├── killableprocess │ ├── __init__.py │ └── qijo.py ├── __init__.py ├── telnet_repl.py ├── autocomplete_server.py ├── sublimepython_repl.py ├── powershell_repl.py ├── execnet_repl.py ├── repl.py ├── sublimehaskell_repl.py ├── sublimeutop_repl.py └── subprocess_repl.py ├── LICENSE.TXT ├── Context.sublime-menu ├── packages.json ├── sublimerepl_build_system_hack.sublime-build ├── sublimerepl_build_system_hack.py ├── LICENSE-LIB.txt ├── completions.py ├── run_existing_command.py ├── Main.sublime-menu ├── messages └── 2.0.0.txt ├── README.md ├── SublimeREPL.sublime-settings ├── Default (Windows).sublime-keymap ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── lang_integration.py └── text_transfer.py /foo.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repllibs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.no-sublime-package: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.bak 3 | doc/_build 4 | -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | *.pyc 3 | doc/_build/* 4 | -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "2.0.0": "messages/2.0.0.txt" 3 | } 4 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals, print_function, division -------------------------------------------------------------------------------- /doc/_static/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuub/SublimeREPL/HEAD/doc/_static/menu.png -------------------------------------------------------------------------------- /doc/_static/palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuub/SublimeREPL/HEAD/doc/_static/palette.png -------------------------------------------------------------------------------- /config/OCaml/OCaml (toplevel).sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "auto_complete_triggers": [ {"selector": "source.ocaml", "characters": "."} ] 3 | } 4 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Restart REPL", 4 | "command": "repl_restart" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /SublimeREPL (OSX).sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | // Add to PATH /usr/local/bin by default on OSX. 3 | "default_extend_env": {"PATH": "{PATH}:/usr/local/bin"} 4 | } 5 | -------------------------------------------------------------------------------- /repls/killableprocess/__init__.py: -------------------------------------------------------------------------------- 1 | from .killableprocess import Popen, mswindows 2 | if mswindows: 3 | from .winprocess import STARTUPINFO, STARTF_USESHOWWINDOW -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | The whole SublimeREPL package is licensed under GNU GENERAL PUBLIC LICENSE Version 2. 2 | 3 | Parts of SublimeREPL might be usable under more permisive terms. See LICENSE-LIB.txt for details. 4 | -------------------------------------------------------------------------------- /Context.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | {"caption": "-"}, 3 | {"command": "repl_kill", "caption": "Kill"}, 4 | {"command": "repl_restart", "caption": "Restart"}, 5 | {"command": "subprocess_repl_send_signal", "caption": "Send other SIGNAL"} 6 | ] -------------------------------------------------------------------------------- /config/F/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: F#", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_f#", 7 | "file": "config/F/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/R/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: R", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_r", 7 | "file": "config/R/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Perl/re.pl: -------------------------------------------------------------------------------- 1 | $| = 1; 2 | 3 | while(true) { 4 | print "perl> "; 5 | $line=<>; 6 | $value=eval($line); 7 | $error=$@; 8 | if( $error ne "" ) { 9 | print $error; 10 | } else { 11 | print "$value\n"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /config/Io/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Io", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_io", 7 | "file": "config/Io/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/Lua/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Lua", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_lua", 7 | "file": "config/Lua/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/PHP/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: PHP", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_php", 7 | "file": "config/PHP/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/SML/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: SML", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_sml", 7 | "file": "config/SML/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/GDB/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: GDB", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_gdb", 7 | "file": "config/GDB/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/NodeJS/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Node", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_node", 7 | "file": "config/NodeJS/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Shell/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Shell", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_shell", 7 | "file": "config/Shell/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Elixir/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Elixir", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_elixir", 7 | "file": "config/Elixir/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Erlang/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Erlang", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_erlang", 7 | "file": "config/Erlang/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Groovy/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Groovy", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_groovy", 7 | "file": "config/Groovy/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Matlab/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Matlab", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_matlab", 7 | "file": "config/Matlab/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Octave/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Octave", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_octave", 7 | "file": "config/Octave/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Perl/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Perl", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_Perl", 7 | "file": "config/Perl/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/Rails/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Rails", 4 | "command": "run_existing_window_command", 5 | "args": { 6 | "id": "repl_rails", 7 | "file": "config/Rails/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/Haskell/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Haskell", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_haskell", 7 | "file": "config/Haskell/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Maxima/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Maxima", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_maxima", 7 | "file": "config/Maxima/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/MozRepl/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: MozRepl", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_mozrepl", 7 | "file": "config/MozRepl/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Racket/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Racket", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_plt_racket", 7 | "file": "config/Racket/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Tower/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Tower Console", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_tower", 7 | "file": "config/Tower/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /repls/__init__.py: -------------------------------------------------------------------------------- 1 | from .repl import * 2 | from .subprocess_repl import * 3 | from .sublimehaskell_repl import * 4 | from .telnet_repl import * 5 | from .sublimepython_repl import * 6 | from .powershell_repl import * 7 | from .sublimeutop_repl import * 8 | # from .execnet_repl import * # disabled for now 9 | -------------------------------------------------------------------------------- /config/ScriptCS/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: ScriptCS", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_scriptcs", 7 | "file": "config/ScriptCS/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/PowerShell/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: PowerShell", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_powershell", 7 | "file": "config/PowerShell/Main.sublime-menu" 8 | } 9 | } 10 | ] -------------------------------------------------------------------------------- /config/Prolog/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Prolog (Sicstus)", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_prolog", 7 | "file": "config/Prolog/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/Execnet/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Python - execnet", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_sublime_execnet", 7 | "file": "config/Execnet/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/CoffeeScript/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: CoffeeScript", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_coffeescript", 7 | "file": "config/CoffeeScript/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/Sublime/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Python - Sublime Text Console", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_sublime_python", 7 | "file": "config/Sublime/Main.sublime-menu" 8 | } 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /config/Clojure/Default.sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["ctrl+f12", "c", "s"], "command": "run_existing_window_command", "args": {"id": "repl_clojure", "file": "config/Clojure/Main.sublime-menu"}}, 3 | { "keys": ["ctrl+f12", "c", "t"], "command": "run_existing_window_command", "args": {"id": "repl_clojure_telnet", "file": "config/Clojure/Main.sublime-menu"}} 4 | ] -------------------------------------------------------------------------------- /packages.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "3.0.0", 3 | "packages": [{ 4 | "name": "SublimeREPL", 5 | "details": "https://github.com/wuub/SublimeREPL", 6 | "description": "SublimeREPL - run an interpreter inside ST2 (Clojure, CoffeeScript, F#, Groovy, Haskell, Lua, MozRepl, NodeJS, Python + virtualenv, R, Ruby, Scala...)", 7 | "releases": [ 8 | { 9 | "sublime_text": "*", 10 | "tags": true 11 | } 12 | ] 13 | }] 14 | } 15 | -------------------------------------------------------------------------------- /config/Scala/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Scala", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_scala", 7 | "file": "config/Scala/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: SBT for opened folder", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_sbt", 15 | "file": "config/Scala/Main.sublime-menu" 16 | } 17 | } 18 | ] -------------------------------------------------------------------------------- /sublimerepl_build_system_hack.sublime-build: -------------------------------------------------------------------------------- 1 | { 2 | "target": "sublimerepl_build_system_hack", 3 | "cmd": { 4 | "file_path": "${file_path}", 5 | "file": "${file}", 6 | "file_name": "${file_name}", 7 | "file_extension": "${file_extension}", 8 | "file_base_name": "${file_base_name}", 9 | "packages": "${packages}", 10 | "project": "${project}", 11 | "project_path": "${project_path}", 12 | "project_name": "${project_name}", 13 | "project_extension": "${project_extension}", 14 | "project_base_name": "${project_base_name}" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /config/OCaml/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: OCaml", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_ocaml", 7 | "file": "config/OCaml/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: OCaml utop", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_ocaml_utop", 15 | "file": "config/OCaml/Main.sublime-menu" 16 | } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /config/Ruby/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Ruby", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_ruby", 7 | "file": "config/Ruby/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: Ruby IRB (deprecated)", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_ruby_irb", 15 | "file": "config/Ruby/Main.sublime-menu" 16 | } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /config/Clojure/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Clojure", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_clojure", 7 | "file": "config/Clojure/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: Clojure-Telnet", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_clojure_telnet", 15 | "file": "config/Clojure/Main.sublime-menu" 16 | } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /config/ClojureScript/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: ClojureScript Browser REPL", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_clojurescript_browser", 7 | "file": "config/ClojureScript/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: ClojureScript", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_clojurescript", 15 | "file": "config/ClojureScript/Main.sublime-menu" 16 | } 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /config/Execnet/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": [ 10 | {"caption": "Python", 11 | "id": "Python", 12 | "children": [ 13 | { 14 | "command": "execnet_virtualenv_repl", 15 | "id": "repl_sublime_execnet", 16 | "caption": "Python - execnet" 17 | } 18 | ]} 19 | ]} 20 | ] 21 | }] 22 | -------------------------------------------------------------------------------- /config/Sublime/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Sublime", 13 | "id": "repl_sublime_python", 14 | "args": { 15 | "type": "sublime_python", 16 | "encoding": "utf8", 17 | "syntax": "Packages/Python/Python.tmLanguage" 18 | } 19 | } 20 | ] 21 | }] 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /config/ClojureScript/clojurescript.tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | comment 6 | ClojureScript 7 | name 8 | ClojureScript 9 | fileTypes 10 | 11 | cljs 12 | 13 | patterns 14 | 15 | 16 | include 17 | source.clojure 18 | 19 | 20 | scopeName 21 | source.clojurescript 22 | 23 | -------------------------------------------------------------------------------- /config/GDB/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "GDB", 13 | "id": "repl_gdb", 14 | "mnemonic": "D", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["gdb"], 19 | "cwd": "$file_path", 20 | "external_id": "gdb" 21 | } 22 | } 23 | ] 24 | }] 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /config/Maxima/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Maxima", 13 | "id": "repl_maxima", 14 | "mnemonic": "M", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["maxima"], 19 | "cwd": "$file_path", 20 | "external_id": "maxima" 21 | } 22 | } 23 | ] 24 | }] 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /config/MozRepl/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "MozRepl", 13 | "mnemonic": "M", 14 | "id": "repl_mozrepl", 15 | "args": { 16 | "type": "telnet", 17 | "encoding": "utf8", 18 | "host":"localhost", 19 | "port": 4242, 20 | "syntax": "Packages/JavaScript/JavaScript.tmLanguage" 21 | } 22 | } 23 | ] 24 | }] 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /config/SML/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "SML", 13 | "id": "repl_sml", 14 | "args": { 15 | "type": "subprocess", 16 | "encoding": "utf8", 17 | "cmd": ["sml"], 18 | "cwd": "$file_path", 19 | "external_id": "sml", 20 | "syntax": "Packages/SML (Standard ML)/sml.tmLanguage" 21 | } 22 | } 23 | ] 24 | }] 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /config/Scheme/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Scheme", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_scheme", 7 | "file": "config/Scheme/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: Gauche", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_gauche", 15 | "file": "config/Scheme/Main.sublime-menu" 16 | } 17 | }, 18 | { 19 | "caption": "SublimeREPL: Petite Chez Scheme", 20 | "command": "run_existing_window_command", "args": 21 | { 22 | "id": "repl_petite", 23 | "file": "config/Scheme/Main.sublime-menu" 24 | } 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /config/Lua/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Lua", 13 | "id": "repl_lua", 14 | "mnemonic": "L", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["lua", "-i"], 19 | "cwd": "$file_path", 20 | "external_id": "lua", 21 | "syntax": "Packages/Lua/Lua.tmLanguage" 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/Haskell/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Haskell", 13 | "id": "repl_haskell", 14 | "mnemonic": "H", 15 | "args": { 16 | "type": "sublime_haskell", 17 | "encoding": "utf8", 18 | "cmd": ["ghci"], 19 | "cwd": "$file_path", 20 | "external_id": "haskell", 21 | "syntax": "Packages/Haskell/Haskell.tmLanguage" 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/Matlab/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Matlab", 13 | "id": "repl_matlab", 14 | "mnemonic": "M", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["matlab", "-nodesktop","-nosplash"], 19 | "cwd": "$file_path", 20 | "external_id": "matlab", 21 | "syntax": "Packages/Matlab/Matlab.tmLanguage" 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/Prolog/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id":"tools", 4 | "children":[ 5 | { 6 | "caption":"SublimeREPL", 7 | "mnemonic":"r", 8 | "id":"SublimeREPL", 9 | "children":[ 10 | { 11 | "caption":"Prolog (Sicstus)", 12 | "command":"repl_open", 13 | "id":"repl_prolog", 14 | "mnemonic":"P", 15 | "args":{ 16 | "type":"subprocess", 17 | "external_id":"prolog", 18 | "encoding":"utf8", 19 | "cmd": ["sicstus"], 20 | "soft_quit":"\nexit\n", 21 | "cwd":"$file_path", 22 | "cmd_postfix":"\n", 23 | "autocomplete_server": true, 24 | "syntax":"Packages/Prolog/Prolog.tmLanguage" 25 | } 26 | } 27 | ] 28 | } 29 | ] 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /config/Elixir/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "id": "repl_elixir", 13 | "caption": "Elixir", 14 | "args": { 15 | "type": "subprocess", 16 | "encoding": "utf8", 17 | "cmd": ["iex"], 18 | "cwd": "$file_path", 19 | "syntax": "Packages/Elixir/Elixir.tmLanguage", 20 | "external_id": "elixir", 21 | "extend_env": {"NODE_DISABLE_COLORS": "1"} 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/Erlang/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "id": "repl_erlang", 13 | "caption": "Erlang", 14 | "args": { 15 | "type": "subprocess", 16 | "encoding": "utf8", 17 | "cmd": ["erl", "-i"], 18 | "cwd": "$file_path", 19 | "syntax": "Packages/Erlang/Erlang.tmLanguage", 20 | "external_id": "erlang", 21 | "extend_env": {"NODE_DISABLE_COLORS": "1"} 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/Perl/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Perl", 13 | "id": "repl_Perl", 14 | "mnemonic": "P", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["perl","${packages}/SublimeREPL/config/Perl/re.pl"], 19 | "cwd": "$file_path", 20 | "external_id": "perl", 21 | "syntax": "Packages/Perl/Perl.tmLanguage" 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/PowerShell/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "PowerShell", 13 | "id": "repl_powershell", 14 | "mnemonic": "P", 15 | "args": { 16 | "type": "powershell", 17 | "encoding": "", 18 | "cmd": ["powershell", "-"], 19 | "cwd": "$file_path", 20 | "external_id": "powershell", 21 | "syntax": "Packages/PowerShell/Support/PowershellSyntax.tmLanguage" 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/Octave/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Octave", 13 | "id": "repl_octave", 14 | "mnemonic": "O", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["octave", "-i"], 19 | "cwd": "$file_path", 20 | "external_id": "octave", 21 | "additional_scopes": ["matlab"], 22 | "syntax": "Packages/Matlab/Matlab.tmLanguage" 23 | } 24 | } 25 | ] 26 | }] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /sublimerepl_build_system_hack.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals, print_function, division 2 | 3 | import sublime_plugin 4 | try: 5 | import queue 6 | except ImportError: 7 | import Queue as queue 8 | 9 | RESULTS = None 10 | HACK_BUILD_SYSTEM = "Packages/SublimeREPL/sublimerepl_build_system_hack.sublime-build" 11 | AUTOMATIC_BUILD_SYSTEM = "" 12 | 13 | 14 | class SublimereplBuildSystemHackCommand(sublime_plugin.WindowCommand): 15 | def run(self, cmd): 16 | RESULTS.put(cmd) 17 | 18 | 19 | def get_project_settings(window): 20 | global RESULTS 21 | try: 22 | RESULTS = queue.Queue() # in case of garbage on RESULTS 23 | window.run_command("set_build_system", {"file": HACK_BUILD_SYSTEM}) 24 | window.run_command("build") 25 | finally: 26 | window.run_command("set_build_system", {"file": AUTOMATIC_BUILD_SYSTEM}) 27 | return RESULTS.get(timeout=1.0) 28 | -------------------------------------------------------------------------------- /config/Tower/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "id": "repl_tower", 13 | "caption": "Tower Console", 14 | "args": { 15 | "cwd": "$file_path", 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["tower", "console", "-c"], 19 | "syntax": "Packages/CoffeeScript/CoffeeScript.tmLanguage", 20 | "external_id": "tower", 21 | "extend_env": {"NODE_DISABLE_COLORS": "1"} 22 | } 23 | } 24 | ] 25 | }] 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /config/CoffeeScript/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "id": "repl_coffeescript", 13 | "caption": "CoffeeScript", 14 | "args": { 15 | "type": "subprocess", 16 | "encoding": "utf8", 17 | "cmd": ["coffee", "-i"], 18 | "cwd": "$file_path", 19 | "syntax": "Packages/CoffeeScript/CoffeeScript.tmLanguage", 20 | "external_id": "coffeescript", 21 | "additional_scopes": ["coffee"], 22 | "extend_env": {"NODE_DISABLE_COLORS": "1"} 23 | } 24 | } 25 | ] 26 | }] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /config/Racket/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": [ 5 | { 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": [ 10 | { 11 | "command": "repl_open", 12 | "caption": "Racket", 13 | "id": "repl_plt_racket", 14 | "mnemonic": "R", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": ["racket"], 19 | "cwd": "$file_path", 20 | "syntax": "Packages/Racket/Racket.tmLanguage", 21 | "external_id": "racket" 22 | } 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | ] -------------------------------------------------------------------------------- /LICENSE-LIB.txt: -------------------------------------------------------------------------------- 1 | LICENSE Libraries and external dependencies 2 | 3 | SublimeREPL is not a monolithic block of code and some REPLs / functions depends on external libraries. 4 | 5 | This means that, although the parts of SublimeREPL that I (wuub) wrote are published under BSD license and you're free to reuse them as you wish, the whole SublimeREPL package is as of now licensed under GPLv2. 6 | 7 | - Remote Python depends on a fantastic execnet library by Holger Krekel (https://bitbucket.org/hpk42/execnet & http://codespeak.net/execnet/ & https://twitter.com/hpk42. execnet is licensed under GPLv2. As a result repls/execnet_repl.py and lang_integration:ExecnetVirtualenvRepl are licensed under GPLv2 as well! 8 | 9 | - Persistent history depends on buzhug library by Pierre Quentel. (http://buzhug.sourceforge.net/ buzhug is published under the revised BSD licence. 10 | 11 | - subprocess_repl depends on killableprocess by Peter Astrand, Mike Taylor and Mikeal Rogers. Please see killableprocess.py for details. 12 | -------------------------------------------------------------------------------- /config/ScriptCS/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "ScriptCS", 13 | "id": "repl_scriptcs", 14 | "mnemonic": "C", 15 | "args": { 16 | "type": "subprocess", 17 | "external_id": "scriptcs", 18 | "encoding": "utf8", 19 | "cmd": { 20 | "windows": ["scriptcs"], 21 | "osx": ["scriptcs"], 22 | "linux": ["scriptcs"]}, 23 | "cwd": "$file_path", 24 | "additional_scopes": ["csx"], 25 | "syntax": "Packages/scriptcs/ScriptCs.tmLanguage" 26 | } 27 | } 28 | ] 29 | }] 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /config/F/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "F#", 13 | "id": "repl_f#", 14 | "mnemonic": "F", 15 | "args": { 16 | "type": "subprocess", 17 | "external_id": "fsharp", 18 | "encoding": "utf8", 19 | "cmd": { 20 | "windows": ["fsi.exe", "--utf8output", "--gui-"], 21 | "osx": ["fsharpi", "--utf8output", "--readline-"], 22 | "linux": ["fsi", "--utf8output", "--readline-"]}, 23 | "cmd_postfix": ";;\n", 24 | "cwd": "$file_path", 25 | "syntax": "Packages/F#/F#.tmLanguage" 26 | } 27 | } 28 | ] 29 | }] 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /config/PHP/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "PHP", 13 | "id": "repl_php", 14 | "mnemonic": "P", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": {"windows": "$win_cmd_encoding", 18 | "linux": "utf-8", 19 | "osx": "utf-8"}, 20 | "cmd": {"windows": ["php.exe", "-a"], 21 | "linux": ["php", "-a"], 22 | "osx": ["php", "-a"]}, 23 | "cwd": "$file_path", 24 | "cmd_postfix": "\n", 25 | "env": {}, 26 | "suppress_echo": false, 27 | "syntax": "Packages/Text/Plain text.tmLanguage" 28 | } 29 | } 30 | ] 31 | }] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /config/Main.sublime-menu.template: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | // {"command": "repl_open", 12 | // "caption": "Command Caption in Menu", 13 | // "mnemonic": "m", 14 | // "args": { 15 | // "type": "subprocess|telnet", 16 | // "encoding": "utf8", 17 | // "cmd": ["bash", "-i"] or "bash -i" on windows, 18 | // "cwd": "$file_path", 19 | // "env": {}, // clean environment for subprocess repl 20 | // "extend_env": {}, // variables to be added to standard env 21 | // "cmd_postfix": "\n", // postfix that will be automatically added after a line in repl 22 | // "suppress_echo": false, // try to remove remote echo 23 | // "syntax": "Packages/Text/Plain text.tmLanguage" 24 | // } 25 | // }, 26 | ] 27 | }] 28 | } 29 | ] 30 | -------------------------------------------------------------------------------- /config/NodeJS/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Node", 13 | "id": "repl_node", 14 | "mnemonic": "N", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": {"linux": ["node", "${packages}/SublimeREPL/config/NodeJS/repl.js"], 19 | "osx": ["node", "${packages}/SublimeREPL/config/NodeJS/repl.js"], 20 | "windows": ["node.exe", "${packages}/SublimeREPL/config/NodeJS/repl.js"]}, 21 | "cwd": "$file_path", 22 | "syntax": "Packages/JavaScript/JavaScript.tmLanguage", 23 | "external_id": "js", 24 | "autocomplete_server": true, 25 | "extend_env": {"NODE_NO_READLINE": 1} 26 | } 27 | } 28 | ] 29 | }] 30 | } 31 | ] 32 | -------------------------------------------------------------------------------- /config/Python/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Python", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_python", 7 | "file": "config/Python/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: Python - PDB current file", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_python_pdb", 15 | "file": "config/Python/Main.sublime-menu" 16 | } 17 | }, 18 | { 19 | "caption": "SublimeREPL: Python - RUN current file", 20 | "command": "run_existing_window_command", "args": 21 | { 22 | "id": "repl_python_run", 23 | "file": "config/Python/Main.sublime-menu" 24 | } 25 | }, 26 | { 27 | "command": "python_virtualenv_repl", 28 | "caption": "SublimeREPL: Python - virtualenv" 29 | }, 30 | { 31 | "caption": "SublimeREPL: Python - IPython", 32 | "command": "run_existing_window_command", "args": 33 | { 34 | "id": "repl_python_ipython", 35 | "file": "config/Python/Main.sublime-menu" 36 | } 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /config/Shell/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Shell", 13 | "id": "repl_shell", 14 | "mnemonic": "S", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": {"windows": "$win_cmd_encoding", 18 | "linux": "utf-8", 19 | "osx": "utf-8"}, 20 | "cmd": {"windows": ["cmd.exe"], 21 | "linux": ["bash", "-i"], 22 | "osx": ["bash", "-i"]}, 23 | "cwd": "$file_path", 24 | "cmd_postfix": "\n", 25 | "env": {}, 26 | "suppress_echo": true, 27 | "external_id": "shell", 28 | "syntax": "Packages/Text/Plain text.tmLanguage" 29 | } 30 | } 31 | ] 32 | }] 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /config/Io/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "Io", 13 | "id": "repl_io", 14 | "mnemonic": "I", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "cmd": {"linux": ["io", "${packages}/SublimeREPL/config/Io/repl.io"], 19 | "windows": ["io", "${packages}/SublimeREPL/config/Io/repl.io"], 20 | "osx": ["io", "${packages}/SublimeREPL/config/Io/repl.io"]}, 21 | "cwd": "$file_path", 22 | "external_id": "io", 23 | "suppress_echo": {"linux": true, 24 | "windows": false, 25 | "osx": true}, 26 | "syntax": "Packages/SublimeREPL/config/Io/Io.tmLanguage" 27 | } 28 | } 29 | ] 30 | }] 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /config/NodeJS/repl.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | var repl = require('repl'); 4 | 5 | var rep = repl.start({ 6 | prompt: null, //'> ', 7 | source: null, //process.stdin, 8 | eval: null, //require('vm').runInThisContext, 9 | useGlobal: true, //false 10 | useColors: false 11 | }); 12 | 13 | 14 | var net = require('net'); 15 | var ac_port = process.env.SUBLIMEREPL_AC_PORT; 16 | var client = new net.Socket(); 17 | client.connect(ac_port, "localhost", function() {}); 18 | 19 | client.on('data', function(data) { 20 | var strData = data.toString(); 21 | var index = strData.indexOf(":"); 22 | var json = strData.slice(index+1, strData.length - 1) 23 | var inData = JSON.parse(json); 24 | var wordIndex = inData.line.slice(inData.cursor_pos).search(/\b/); 25 | if(wordIndex !== 0){ 26 | inData.line = inData.line.slice(0, inData.cursor_pos); 27 | } 28 | 29 | var send = function (_, completions) { 30 | var comps = completions[0]; 31 | var msg = JSON.stringify([inData.line, comps]); 32 | var payload = msg.length + ":" + msg + ","; 33 | client.write(payload) 34 | } 35 | rep.rli.completer(inData.line, send); 36 | }); 37 | 38 | })(); 39 | -------------------------------------------------------------------------------- /completions.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals, print_function, division 2 | 3 | import sublime 4 | import sublime_plugin 5 | 6 | 7 | 8 | class SublimeREPLCompletions(sublime_plugin.EventListener): 9 | def on_query_completions(self, view, prefix, locations): 10 | try: 11 | from .sublimerepl import manager 12 | except ValueError: 13 | from sublimerepl import manager 14 | 15 | if not view.settings().get("repl"): 16 | return True 17 | 18 | rv = manager.repl_view(view) 19 | if not rv: 20 | return [] 21 | 22 | repl = rv.repl 23 | if not repl.autocomplete_available(): 24 | return [] 25 | 26 | line = view.line(locations[0]) 27 | 28 | start = max(line.begin(), rv._output_end) 29 | end = line.end() 30 | 31 | whole_line = view.substr(sublime.Region(start, end)) 32 | pos_in_line = locations[0] - start 33 | whole_prefix = whole_line[:pos_in_line] 34 | 35 | completions = repl.autocomplete_completions( 36 | whole_line=whole_line, 37 | pos_in_line=pos_in_line, 38 | prefix=prefix, 39 | whole_prefix=whole_prefix, 40 | locations=locations) 41 | return completions, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS 42 | -------------------------------------------------------------------------------- /config/Groovy/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "id": "repl_groovy", 13 | "caption": "Groovy", 14 | "mnemonic": "G", 15 | "args": { 16 | "type": "subprocess", 17 | "encoding": "utf8", 18 | "external_id": "groovy", 19 | "cmd": {"linux": ["groovysh", "--terminal=none"], 20 | "osx": ["groovysh", "--terminal=none"], 21 | "windows": ["groovysh.bat", "--terminal=none"]}, 22 | "soft_quit": "\nexit\n", 23 | "cwd": "$file_path", 24 | "cmd_postfix": "\n", 25 | "extend_env": {"osx": {"PATH": "{PATH}:/usr/local/bin"}, 26 | "linux": {"PATH": "{PATH}:/usr/local/bin"}, 27 | "windows": {}}, 28 | "suppress_echo": false, 29 | "syntax": "Packages/Groovy/Groovy.tmLanguage" 30 | } 31 | } 32 | ] 33 | }] 34 | } 35 | ] 36 | -------------------------------------------------------------------------------- /config/OCaml/OCaml (toplevel).tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | OCaml (toplevel) 7 | patterns 8 | 9 | 10 | begin 11 | ^# 12 | end 13 | (;;|^(?=! )) 14 | name 15 | source.ocaml.toplevel.embedded.input 16 | patterns 17 | 18 | 19 | include 20 | source.ocaml 21 | 22 | 23 | 24 | 25 | begin 26 | ^- 27 | end 28 | ^(?=#) 29 | name 30 | source.ocaml.toplevel.embedded.value 31 | patterns 32 | 33 | 34 | include 35 | source.ocaml 36 | 37 | 38 | 39 | 40 | begin 41 | ^! 42 | end 43 | $ 44 | name 45 | invalid.ocaml.toplevel.stderr 46 | 47 | 48 | scopeName 49 | source.ocaml.toplevel 50 | uuid 51 | d1a342ce-4108-11e3-b309-1b404228fc7c 52 | 53 | 54 | -------------------------------------------------------------------------------- /config/Rails/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "Rails", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | { 12 | "command": "repl_open", 13 | "caption": "Rails", 14 | "id": "repl_rails", 15 | "external_id":"rails", 16 | "mnemonic": "R", 17 | "args": 18 | { 19 | "type": "subprocess", 20 | "encoding": {"windows": "$win_cmd_encoding", 21 | "linux": "utf-8", 22 | "osx": "utf-8"}, 23 | "cmd": { "windows": ["ruby.exe", "${packages}/SublimeREPL/config/Rails/pry_repl.rb", "$editor"], 24 | "linux": ["ruby", "${packages}/SublimeREPL/config/Rails/pry_repl.rb", "$editor"], 25 | "osx": ["ruby", "${packages}/SublimeREPL/config/Rails/pry_repl.rb", "$editor"] }, 26 | "env": {}, 27 | "soft_quit":"\nexit\n", 28 | "cwd":"$folder", 29 | "cmd_postfix":"\n", 30 | "autocomplete_server": true, 31 | "syntax": "Packages/Ruby/Ruby.tmLanguage" 32 | } 33 | } 34 | ] 35 | }] 36 | } 37 | ] 38 | -------------------------------------------------------------------------------- /config/Clojure/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"caption": "Clojure", 12 | "id": "Clojure", 13 | "children":[ 14 | {"command": "repl_open", 15 | "caption": "Clojure", 16 | "id": "repl_clojure", 17 | "args": { 18 | "type": "subprocess", 19 | "encoding": "utf8", 20 | "cmd": {"windows": ["lein.bat", "repl"], 21 | "linux": ["lein", "repl"], 22 | "osx": ["lein", "repl"]}, 23 | "soft_quit": "\n(. System exit 0)\n", 24 | "cwd": {"windows":"c:/Clojure", 25 | "linux": "$file_path", 26 | "osx": "$file_path"}, 27 | "syntax": "Packages/Clojure/Clojure.tmLanguage", 28 | "external_id": "clojure", 29 | "extend_env": {"INSIDE_EMACS": "1"} 30 | } 31 | }, 32 | {"command": "clojure_auto_telnet_repl", 33 | "id": "repl_clojure_telnet", 34 | "caption": "Clojure-Telnet"}]} 35 | ] 36 | }] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /repls/telnet_repl.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2011, Wojciech Bederski (wuub.net) 3 | # All rights reserved. 4 | # See LICENSE.txt for details. 5 | 6 | import telnetlib 7 | from . import repl 8 | 9 | class TelnetRepl(repl.Repl): 10 | TYPE = "telnet" 11 | 12 | def __init__(self, encoding, host="localhost", port=23, **kwds): 13 | """Create new TelnetRepl with the following initial values: 14 | encoding: one of python accepted encoding used to encode commands and decode responses 15 | external_id: external, persisten name of this repl used to find it later 16 | host: telnet host to connect to 17 | port: telnet port to connect to 18 | cmd_postfix: some REPLS require you to end a command with a postfix to begin execution, 19 | think ';' or '.', you can force repl to add it automatically""" 20 | super(TelnetRepl, self).__init__(encoding, **kwds) 21 | self._telnet = telnetlib.Telnet() 22 | #convert to int for user's sake, we don't care if it's an float or string 23 | # as long as it can be turned into an INT 24 | self._telnet.open(host, int(port)) 25 | self._alive = True 26 | self._killed = False 27 | 28 | def name(self): 29 | return "%s:%s" % (self._telnet.host, self._telnet.port) 30 | 31 | def is_alive(self): 32 | return self._alive 33 | 34 | def read_bytes(self): 35 | return self._telnet.read_some() 36 | 37 | def write_bytes(self, bytes): 38 | self._telnet.write(bytes) 39 | 40 | def kill(self): 41 | self._killed = True 42 | self._telnet.close() 43 | self._alive = False 44 | -------------------------------------------------------------------------------- /config/Rails/pry_repl.rb: -------------------------------------------------------------------------------- 1 | # Simply merged `pry_repl.rb` from the Ruby REPL and - https://github.com/doitian/rails-console-pry 2 | 3 | require 'rubygems' 4 | gem 'pry' 5 | require 'pry' 6 | require 'thread' 7 | require 'json' 8 | require 'pry-rails/version' 9 | pry_rails_path = Gem.loaded_specs['pry-rails'] 10 | 11 | class PryInput 12 | def readline(prompt) 13 | $stdout.print prompt 14 | $stdout.flush 15 | $stdin.readline 16 | end 17 | end 18 | 19 | class PryOutput 20 | def puts(data="") 21 | $stdout.puts(data.gsub('`', "'")) 22 | $stdout.flush 23 | end 24 | end 25 | 26 | Pry.config.input = PryInput.new() 27 | Pry.config.output = PryOutput.new() 28 | Pry.config.color = false 29 | Pry.config.editor = ARGV[0] 30 | Pry.config.auto_indent = false 31 | Pry.config.correct_indent = false 32 | 33 | port = ENV["SUBLIMEREPL_AC_PORT"].to_i 34 | 35 | completer = Pry::InputCompleter.build_completion_proc(binding) 36 | 37 | def read_netstring(s) 38 | size = 0 39 | while true 40 | ch = s.recvfrom(1)[0] 41 | if ch == ':' 42 | break 43 | end 44 | size = size * 10 + ch.to_i 45 | end 46 | msg = "" 47 | while size != 0 48 | msg += s.recvfrom(size)[0] 49 | size -= msg.length 50 | end 51 | ch = s.recvfrom(1)[0] 52 | return msg 53 | end 54 | 55 | ENV['RAILS_ENV'] = "development" 56 | 57 | APP_PATH = File.expand_path('config/application') 58 | require APP_PATH 59 | 60 | if ::Rails::VERSION::MAJOR >= 3 61 | class ::Rails::Console 62 | end 63 | end 64 | 65 | ARGV.unshift "console" 66 | 67 | $: << File.join(pry_rails_path.full_gem_path, 'lib') 68 | require 'pry-rails' 69 | 70 | require 'rails/commands' 71 | 72 | -------------------------------------------------------------------------------- /config/R/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"command": "repl_open", 12 | "caption": "R", 13 | "id": "repl_r", 14 | "mnemonic": "R", 15 | "args": { 16 | "type": "subprocess", 17 | "external_id": "r", 18 | "additional_scopes": ["tex.latex.knitr"], 19 | "encoding": { 20 | "windows": "$win_cmd_encoding", 21 | "linux": "utf8", 22 | "osx": "utf8" 23 | }, 24 | "soft_quit": "\nquit(save=\"no\")\n", 25 | "cmd": {"linux": ["R", "--interactive", "--no-readline"], 26 | "osx": ["R", "--interactive", "--no-readline"], 27 | "windows": ["Rterm.exe", "--ess", "--encoding=$win_cmd_encoding"]}, 28 | "cwd": "$file_path", 29 | "extend_env": {"osx": {"PATH": "{PATH}:/usr/local/bin"}, 30 | "linux": {"PATH": "{PATH}:/usr/local/bin"}, 31 | "windows": {}}, 32 | "cmd_postfix": "\n", 33 | "suppress_echo": {"osx": true, 34 | "linux": true, 35 | "windows": false}, 36 | "syntax": "Packages/R/R Console.tmLanguage" 37 | } 38 | } 39 | ] 40 | }] 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /config/CommonLisp/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "SublimeREPL: Clozure CL", 4 | "command": "run_existing_window_command", "args": 5 | { 6 | "id": "repl_ccl", 7 | "file": "config/CommonLisp/Main.sublime-menu" 8 | } 9 | }, 10 | { 11 | "caption": "SublimeREPL: SBCL", 12 | "command": "run_existing_window_command", "args": 13 | { 14 | "id": "repl_sbcl", 15 | "file": "config/CommonLisp/Main.sublime-menu" 16 | } 17 | }, 18 | { 19 | "caption": "SublimeREPL: GNU Clisp", 20 | "command": "run_existing_window_command", "args": 21 | { 22 | "id": "repl_clisp", 23 | "file": "config/CommonLisp/Main.sublime-menu" 24 | } 25 | }, 26 | { 27 | "caption": "SublimeREPL: Allegro CL", 28 | "command": "run_existing_window_command", "args": 29 | { 30 | "id": "repl_allegro", 31 | "file": "config/CommonLisp/Main.sublime-menu" 32 | } 33 | }, 34 | { 35 | "caption": "SublimeREPL: ABCL", 36 | "command": "run_existing_window_command", "args": 37 | { 38 | "id": "repl_abcl", 39 | "file": "config/CommonLisp/Main.sublime-menu" 40 | } 41 | }, 42 | { 43 | "caption": "SublimeREPL: CMUCL", 44 | "command": "run_existing_window_command", "args": 45 | { 46 | "id": "repl_cmucl", 47 | "file": "config/CommonLisp/Main.sublime-menu" 48 | } 49 | }, 50 | { 51 | "caption": "SublimeREPL: ECL", 52 | "command": "run_existing_window_command", "args": 53 | { 54 | "id": "repl_ecl", 55 | "file": "config/CommonLisp/Main.sublime-menu" 56 | } 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /config/Ruby/pry_repl.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | gem 'pry' 3 | require 'pry' 4 | require 'socket' 5 | require 'thread' 6 | require 'json' 7 | 8 | include Socket::Constants 9 | 10 | class PryInput 11 | def readline(prompt) 12 | $stdout.print prompt 13 | $stdout.flush 14 | $stdin.readline 15 | end 16 | end 17 | 18 | class PryOutput 19 | def puts(data="") 20 | $stdout.puts(data.gsub('`', "'")) 21 | $stdout.flush 22 | end 23 | end 24 | 25 | Pry.config.input = PryInput.new() 26 | Pry.config.output = PryOutput.new() 27 | Pry.config.color = false 28 | Pry.config.editor = ARGV[0] 29 | Pry.config.auto_indent = false 30 | Pry.config.correct_indent = false 31 | 32 | port = ENV["SUBLIMEREPL_AC_PORT"].to_i 33 | 34 | socket = Socket.new(AF_INET, SOCK_STREAM, 0) 35 | sockaddr = Socket.pack_sockaddr_in(port, '127.0.0.1') 36 | socket.connect(sockaddr) 37 | completer = Pry::InputCompleter.build_completion_proc(binding) 38 | 39 | def read_netstring(s) 40 | size = 0 41 | while true 42 | ch = s.recvfrom(1)[0] 43 | if ch == ':' 44 | break 45 | end 46 | size = size * 10 + ch.to_i 47 | end 48 | msg = "" 49 | while size != 0 50 | msg += s.recvfrom(size)[0] 51 | size -= msg.length 52 | end 53 | ch = s.recvfrom(1)[0] 54 | return msg 55 | end 56 | 57 | # Thread.abort_on_exception = true 58 | t1 = Thread.new do 59 | while true 60 | data = read_netstring(socket) 61 | req = JSON.parse(data) 62 | line = req["line"] 63 | completions = completer.call(req["line"]) 64 | response = [line, completions] 65 | response_msg = JSON.dump(response) 66 | payload = response_msg.length.to_s + ":" + response_msg + "," 67 | socket.write(payload) 68 | end 69 | end 70 | 71 | 72 | Pry.start self 73 | -------------------------------------------------------------------------------- /repls/autocomplete_server.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import json 4 | import socket 5 | import threading 6 | import sublime 7 | 8 | def read_netstring(s): 9 | size = 0 10 | while True: 11 | byte = s.recv(1) 12 | if byte == b':': 13 | break 14 | size = size * 10 + int(byte) 15 | msg = b"" 16 | while size != 0: 17 | msg += s.recv(size) 18 | size -= len(msg) 19 | byte = s.recv(1) 20 | assert byte == b',' 21 | return msg.decode("utf-8") 22 | 23 | def send_netstring(s, msg): 24 | payload = "".join([str(len(msg)), ':', msg, ',']).encode("utf-8") 25 | s.sendall(payload) 26 | 27 | 28 | class AutocompleteServer(object): 29 | def __init__(self, repl, server_ip="127.0.0.1"): 30 | self._repl = repl 31 | self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 32 | self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 33 | self._cli_sock = None 34 | self._server_ip = server_ip 35 | 36 | def start(self): 37 | self._sock.bind((self._server_ip, 0)) 38 | threading.Thread(target=self._wait).start() 39 | 40 | def _wait(self): 41 | self._sock.listen(1) 42 | s, address = self._sock.accept() 43 | self._cli_sock = s 44 | 45 | def port(self): 46 | return self._sock.getsockname()[1] 47 | 48 | def connected(self): 49 | return bool(self._cli_sock) 50 | 51 | def complete(self, whole_line, pos_in_line, prefix, whole_prefix, locations): 52 | req = json.dumps({"text": "", "line": whole_line, "cursor_pos": pos_in_line}) 53 | send_netstring(self._cli_sock, req) 54 | self._cli_sock.settimeout(4) 55 | msg = read_netstring(self._cli_sock) 56 | self._cli_sock.settimeout(None) 57 | res = json.loads(msg) 58 | if not res: 59 | return [] 60 | return [(x, x) for x in res[1]] 61 | -------------------------------------------------------------------------------- /run_existing_command.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals, print_function, division 2 | 3 | import os 4 | import os.path 5 | import sys 6 | import json 7 | import sublime 8 | import sublime_plugin 9 | 10 | SUBLIMEREPL_DIR = None 11 | SUBLIMEREPL_USER_DIR = None 12 | 13 | def plugin_loaded(): 14 | global SUBLIMEREPL_DIR 15 | global SUBLIMEREPL_USER_DIR 16 | SUBLIMEREPL_DIR = "Packages/SublimeREPL" 17 | SUBLIMEREPL_USER_DIR = os.path.join(sublime.packages_path(), "User", "SublimeREPL") 18 | 19 | PY2 = False 20 | if sys.version_info[0] == 2: 21 | SUBLIMEREPL_DIR = os.getcwdu() 22 | SUBLIMEREPL_USER_DIR = os.path.join(sublime.packages_path(), "User", "SublimeREPL") 23 | PY2 = True 24 | 25 | # yes, CommandCommmand :) 26 | class RunExistingWindowCommandCommand(sublime_plugin.WindowCommand): 27 | def run(self, id, file): 28 | """Find and run existing command with id in specified file. 29 | SUBLIMEREPL_USER_DIR is consulted first, and then SUBLIMEREPL_DIR""" 30 | for prefix in (SUBLIMEREPL_USER_DIR, SUBLIMEREPL_DIR): 31 | path = os.path.join(prefix, file) 32 | json_cmd = self._find_cmd(id, path) 33 | if json_cmd: 34 | break 35 | if not json_cmd: 36 | return 37 | args = json_cmd["args"] if "args" in json_cmd else None 38 | self.window.run_command(json_cmd["command"], args) 39 | 40 | def _find_cmd(self, id, file): 41 | return self._find_cmd_in_file(id, file) 42 | 43 | def _find_cmd_in_file(self, id, file): 44 | try: 45 | if PY2 or os.path.isfile(file): 46 | with open(file) as f: 47 | bytes = f.read() 48 | else: 49 | bytes = sublime.load_resource(file) 50 | except (IOError, ValueError): 51 | return None 52 | else: 53 | data = json.loads(bytes) 54 | return self._find_cmd_in_json(id, data) 55 | 56 | def _find_cmd_in_json(self, id, json_object): 57 | if isinstance(json_object, list): 58 | for elem in json_object: 59 | cmd = self._find_cmd_in_json(id, elem) 60 | if cmd: 61 | return cmd 62 | elif isinstance(json_object, dict): 63 | if "id" in json_object and json_object["id"] == id: 64 | return json_object 65 | elif "children" in json_object: 66 | return self._find_cmd_in_json(id, json_object["children"]) 67 | return None -------------------------------------------------------------------------------- /config/ClojureScript/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"caption": "ClojureScript", 12 | "id": "ClojureScript", 13 | "children":[ 14 | {"command": "repl_open", 15 | "caption": "ClojureScript Browser REPL", 16 | "id": "repl_clojurescript_browser", 17 | "args": { 18 | "type": "subprocess", 19 | "encoding": "utf8", 20 | "cmd": {"windows": ["lein.bat", "trampoline", "cljsbuild", "repl-listen"], 21 | "linux": ["lein", "trampoline", "cljsbuild", "repl-listen"], 22 | "osx": ["lein", "trampoline", "cljsbuild", "repl-listen"]}, 23 | "soft_quit": "\n(. System exit 0)\n", 24 | "cwd": {"windows":"c:/Clojure", 25 | "linux": "$file_path", 26 | "osx": "$file_path"}, 27 | "syntax": "Packages/Clojure/Clojure.tmLanguage", 28 | "external_id": "clojurescript", 29 | "extend_env": {"INSIDE_EMACS": "1"} 30 | } 31 | }, 32 | {"command": "repl_open", 33 | "caption": "ClojureScript", 34 | "id": "repl_clojurescript", 35 | "args": { 36 | "type": "subprocess", 37 | "encoding": "utf8", 38 | "cmd": {"windows": ["lein.bat", "trampoline", "cljsbuild", "repl-rhino"], 39 | "linux": ["lein", "trampoline", "cljsbuild", "repl-rhino"], 40 | "osx": ["lein", "trampoline", "cljsbuild", "repl-rhino"]}, 41 | "soft_quit": "\n(. System exit 0)\n", 42 | "cwd": {"windows":"c:/Clojure", 43 | "linux": "$file_path", 44 | "osx": "$file_path"}, 45 | "syntax": "Packages/Clojure/Clojure.tmLanguage", 46 | "external_id": "clojurescript", 47 | "extend_env": {"INSIDE_EMACS": "1"} 48 | } 49 | } 50 | ]} 51 | ] 52 | }] 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /config/Scala/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"caption": "Scala", 12 | "id": "Scala", 13 | 14 | "children":[ 15 | {"command": "repl_open", 16 | "caption": "scala REPL", 17 | "id": "repl_scala", 18 | "mnemonic": "s", 19 | "args": { 20 | "type": "subprocess", 21 | "encoding": "utf8", 22 | "external_id": "scala", 23 | "cmd": {"linux": ["scala"], 24 | "osx": ["scala"], 25 | "windows": ["scala.bat", "-i"]}, 26 | "soft_quit": "\nexit\n", 27 | "cwd": "$file_path", 28 | "cmd_postfix": "\n", 29 | "extend_env": {"osx": {"EMACS": "1", "PATH": "{PATH}:/usr/local/bin"}, 30 | "linux": {"EMACS": "1", "PATH": "{PATH}:/usr/local/bin"}, 31 | "windows": {"EMACS": "1"}}, 32 | "suppress_echo": false, 33 | "syntax": "Packages/Scala/Scala.tmLanguage" 34 | } 35 | }, 36 | {"command": "repl_open", 37 | "caption": "SBT for opened folder", 38 | "id": "repl_sbt", 39 | "mnemonic": "B", 40 | "args": { 41 | "type": "subprocess", 42 | "encoding": "utf8", 43 | "external_id": "scala", 44 | "cmd": {"linux": ["sbt"], 45 | "osx": ["sbt"], 46 | "windows": ["sbt"]}, 47 | "soft_quit": "\nexit\n", 48 | "cwd": "$folder", 49 | "cmd_postfix": "\n", 50 | "extend_env": {"osx": {"EMACS": "1", "PATH": "{PATH}:/usr/local/bin"}, 51 | "linux": {"EMACS": "1", "PATH": "{PATH}:/usr/local/bin"}, 52 | "windows": {"EMACS": "1"}}, 53 | "suppress_echo": false, 54 | "syntax": "Packages/Scala/Scala.tmLanguage" 55 | } 56 | } 57 | ]} 58 | ] 59 | }] 60 | } 61 | ] 62 | -------------------------------------------------------------------------------- /config/OCaml/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id":"tools", 4 | "children":[ 5 | { 6 | "caption":"SublimeREPL", 7 | "mnemonic":"R", 8 | "id":"SublimeREPL", 9 | "children":[ 10 | { 11 | "caption":"OCaml", 12 | "children":[ 13 | { 14 | "command":"repl_open", 15 | "caption":"OCaml toplevel", 16 | "id":"repl_ocaml", 17 | "mnemonic":"t", 18 | "args":{ 19 | "type":"subprocess", 20 | "external_id":"ocaml", 21 | "encoding":"utf8", 22 | "cmd":{ 23 | "windows":[ 24 | "ocaml.exe" 25 | ], 26 | "linux":[ 27 | "ocaml" 28 | ], 29 | "osx":[ 30 | "ocaml" 31 | ] 32 | }, 33 | "soft_quit":"\n#quit;;\n", 34 | "cwd":"$file_path", 35 | "cmd_postfix":";;\n", 36 | "autocomplete_server": false, 37 | "syntax":"Packages/SublimeREPL/config/OCaml/OCaml (toplevel).tmLanguage" 38 | } 39 | }, 40 | { 41 | "command":"repl_open", 42 | "caption":"OCaml utop", 43 | "id":"repl_ocaml_utop", 44 | "mnemonic":"u", 45 | "args":{ 46 | "type":"sublime_utop", 47 | "external_id":"ocaml", 48 | "encoding":"utf8", 49 | "cmd":{ 50 | "windows":[ 51 | "utop.exe", "-emacs" 52 | ], 53 | "linux":[ 54 | "utop", "-emacs" 55 | ], 56 | "osx":[ 57 | "utop", "-emacs" 58 | ] 59 | }, 60 | "soft_quit":"\n#quit;;\n", 61 | "cwd":"$file_path", 62 | "cmd_postfix":"", 63 | "extend_env": { 64 | "OCAML_TOPLEVEL_PATH": "{HOME}/.opam/system/lib/toplevel", 65 | "CAML_LD_LIBRARY_PATH": "{HOME}/.opam/system/lib/stublibs:/usr/lib/ocaml/stublibs", 66 | "PATH": "{PATH}:{HOME}/.opam/system/bin" 67 | }, 68 | "autocomplete_server": false, 69 | "syntax":"Packages/SublimeREPL/config/OCaml/OCaml (toplevel).tmLanguage" 70 | } 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /config/Ruby/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id":"tools", 4 | "children":[ 5 | { 6 | "caption":"SublimeREPL", 7 | "mnemonic":"R", 8 | "id":"SublimeREPL", 9 | "children":[ 10 | { 11 | "caption":"Ruby", 12 | "children":[ 13 | { 14 | "command":"repl_open", 15 | "caption":"Ruby", 16 | "id":"repl_ruby", 17 | "mnemonic":"R", 18 | "args":{ 19 | "type":"subprocess", 20 | "external_id":"ruby", 21 | "encoding":"utf8", 22 | "cmd":{ 23 | "windows":[ 24 | "ruby.exe", 25 | "${packages}/SublimeREPL/config/Ruby/pry_repl.rb", 26 | "$editor" 27 | ], 28 | "linux":[ 29 | "ruby", 30 | "${packages}/SublimeREPL/config/Ruby/pry_repl.rb", 31 | "$editor" 32 | ], 33 | "osx":[ 34 | "ruby", 35 | "${packages}/SublimeREPL/config/Ruby/pry_repl.rb", 36 | "$editor" 37 | ] 38 | }, 39 | "soft_quit":"\nexit\n", 40 | "cwd":"$file_path", 41 | "cmd_postfix":"\n", 42 | "autocomplete_server": true, 43 | "syntax":"Packages/Ruby/Ruby.tmLanguage" 44 | } 45 | }, 46 | { 47 | "command":"repl_open", 48 | "caption":"Ruby - IRB (deprecated)", 49 | "id":"repl_ruby_irb", 50 | "mnemonic":"I", 51 | "args":{ 52 | "type":"subprocess", 53 | "external_id":"ruby", 54 | "encoding":"utf8", 55 | "cmd":{ 56 | "windows":[ 57 | "irb.bat", 58 | "--noreadline", 59 | "--inf-ruby-mode" 60 | ], 61 | "linux":[ 62 | "irb", 63 | "--noreadline", 64 | "--inf-ruby-mode" 65 | ], 66 | "osx":[ 67 | "irb", 68 | "--noreadline", 69 | "--inf-ruby-mode" 70 | ] 71 | }, 72 | "soft_quit":"\nexit\n", 73 | "cwd":"$file_path", 74 | "cmd_postfix":"\n", 75 | "suppress_echo":true, 76 | "syntax":"Packages/Ruby/Ruby.tmLanguage" 77 | } 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | ] 84 | } 85 | ] 86 | -------------------------------------------------------------------------------- /repls/sublimepython_repl.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import code 3 | import contextlib 4 | from .repl import Repl 5 | try: 6 | from queue import Queue 7 | except ImportError: 8 | from Queue import Queue 9 | import sys 10 | import threading 11 | import sublime 12 | 13 | 14 | class QueueOut(object): 15 | def __init__(self, queue): 16 | self.queue = queue 17 | 18 | def write(self, data): 19 | self.queue.put(data) 20 | 21 | 22 | @contextlib.contextmanager 23 | def redirect_stdio(queue): 24 | orig = (sys.stdout, sys.stderr) 25 | sys.stdout = sys.stderr = QueueOut(queue) 26 | yield 27 | (sys.stdout, sys.stderr) = orig 28 | 29 | 30 | class SublimeLocals(dict): 31 | def __init__(self, *args, **kwds): 32 | import pydoc 33 | super(SublimeLocals, self).__init__(*args, **kwds) 34 | self['sublime'] = sublime 35 | self['__name__'] = "__main__" 36 | self['view'] = None 37 | self['window'] = None 38 | self['help'] = pydoc.help 39 | 40 | def __getitem__(self, key): 41 | if key == 'window': 42 | return sublime.active_window() 43 | if key == 'view': 44 | return sublime.active_window().active_view() 45 | return super(SublimeLocals, self).__getitem__(key) 46 | 47 | 48 | class InterceptingConsole(code.InteractiveConsole): 49 | PS1 = ">>> " 50 | PS2 = "... " 51 | 52 | def __init__(self, encoding): 53 | code.InteractiveConsole.__init__(self, locals=SublimeLocals()) 54 | self.input = Queue() 55 | self.output = Queue() 56 | self.output.put(self.PS1) 57 | self._encoding = encoding 58 | 59 | def write(self, data): 60 | self.output.put(data) 61 | 62 | def push(self, line): 63 | with redirect_stdio(self.output): 64 | more = code.InteractiveConsole.push(self, line.decode(self._encoding)) 65 | self.output.put(self.PS2 if more else self.PS1) 66 | return more 67 | 68 | def run(self): 69 | while True: 70 | line = self.input.get() 71 | if line is None: 72 | break 73 | self.push(line) 74 | 75 | 76 | class SublimePythonRepl(Repl): 77 | TYPE = "sublime_python" 78 | 79 | def __init__(self, encoding): 80 | super(SublimePythonRepl, self).__init__(encoding, "python", "\n", False) 81 | self._console = InterceptingConsole(encoding) 82 | self._thread = threading.Thread(target=self._console.run) 83 | self._thread.start() 84 | 85 | def name(self): 86 | return "sublime" 87 | 88 | def is_alive(self): 89 | return True 90 | 91 | def write_bytes(self, bytes): 92 | self._console.input.put(bytes) 93 | 94 | def read_bytes(self): 95 | return self._console.output.get().encode(self._encoding) 96 | 97 | def kill(self): 98 | self._console.input.put(None) 99 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"caption": "Eval in REPL", 12 | "children": 13 | [ 14 | {"caption": "Selection", "command": "repl_transfer_current", "args": {"scope": "selection"}}, 15 | {"caption": "File", "command": "repl_transfer_current", "args": {"scope": "file"}}, 16 | {"caption": "Lines", "command": "repl_transfer_current", "args": {"scope": "lines"}}, 17 | {"caption": "Block", "command": "repl_transfer_current", "args": {"scope": "block"}} 18 | ]}, 19 | {"caption": "Transfer to REPL", 20 | "children": 21 | [ 22 | {"caption": "Selection", "command": "repl_transfer_current", "args": {"scope": "selection", "action":"view_write"}}, 23 | {"caption": "File", "command": "repl_transfer_current", "args": {"scope": "file", "action":"view_write"}}, 24 | {"caption": "Lines", "command": "repl_transfer_current", "args": {"scope": "lines", "action":"view_write"}}, 25 | {"caption": "Block", "command": "repl_transfer_current", "args": {"scope": "block", "action":"view_write"}} 26 | ] 27 | }, 28 | { "caption": "-" } 29 | ] 30 | }] 31 | }, 32 | 33 | { 34 | "caption": "Preferences", 35 | "mnemonic": "n", 36 | "id": "preferences", 37 | "children": 38 | [ 39 | { 40 | "caption": "Package Settings", 41 | "mnemonic": "P", 42 | "id": "package-settings", 43 | "children": 44 | [ 45 | { 46 | "caption": "SublimeREPL", 47 | "children": 48 | [ 49 | { 50 | "command": "open_file", "args": 51 | { 52 | "file": "${packages}/SublimeREPL/SublimeREPL.sublime-settings" 53 | }, 54 | "caption": "Settings – Default" 55 | }, 56 | { 57 | "command": "open_file", "args": 58 | { 59 | "file": "${packages}/User/SublimeREPL.sublime-settings" 60 | }, 61 | "caption": "Settings – User" 62 | }, 63 | { "caption": "-" } 64 | ] 65 | } 66 | ] 67 | } 68 | ] 69 | } 70 | ] 71 | -------------------------------------------------------------------------------- /config/Scheme/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"caption": "Scheme", 12 | "id": "Scheme", 13 | 14 | "children":[ 15 | {"command": "repl_open", 16 | "caption": "Scheme", 17 | "id": "repl_scheme", 18 | "mnemonic": "S", 19 | "args": { 20 | "type": "subprocess", 21 | "encoding": "utf8", 22 | "external_id": "scheme", 23 | "cmd": {"linux": ["scheme"], 24 | "osx": ["scheme"], 25 | "windows": ["scheme"]}, 26 | "soft_quit": "\nexit\n", 27 | "cwd": "$folder", 28 | "cmd_postfix": "\n", 29 | "extend_env": {"INSIDE_EMACS": "1"}, 30 | "syntax": "Packages/sublime-scheme-syntax/Scheme.tmLanguage" 31 | } 32 | }, 33 | {"command": "repl_open", 34 | "caption": "Gauche", 35 | "id": "repl_gauche", 36 | "mnemonic": "G", 37 | "args": { 38 | "type": "subprocess", 39 | "encoding": "utf8", 40 | "external_id": "gauche", 41 | "cmd": {"linux": ["gosh", "-i"], 42 | "osx": ["gosh", "-i"], 43 | "windows": ["gosh", "-i"]}, 44 | "soft_quit": "\n(exit)\n", 45 | "cwd": "$folder", 46 | "cmd_postfix": "\n", 47 | "extend_env": {"INSIDE_EMACS": "1"}, 48 | "syntax": "Packages/Gauche/Gauche.tmLanguage" 49 | } 50 | }, 51 | {"command": "repl_open", 52 | "caption": "Petite Chez Scheme", 53 | "id": "repl_petite", 54 | "mnemonic": "P", 55 | "args": { 56 | "type": "subprocess", 57 | "encoding": "utf8", 58 | "external_id": "petite", 59 | "cmd": {"linux": ["petite"], 60 | "osx": ["petite"], 61 | "windows": ["petite"]}, 62 | "soft_quit": "\n(exit)\n", 63 | "cwd": "$folder", 64 | "cmd_postfix": "\n", 65 | "extend_env": {"INSIDE_EMACS": "1"}, 66 | "syntax": "Packages/sublime-scheme-syntax/Scheme.tmLanguage" 67 | } 68 | } 69 | ]} 70 | ] 71 | }] 72 | } 73 | ] 74 | -------------------------------------------------------------------------------- /repls/powershell_repl.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2011, Wojciech Bederski (wuub.net) 3 | # All rights reserved. 4 | # See LICENSE.txt for details. 5 | import os 6 | import re 7 | from . import subprocess_repl 8 | 9 | # PowerShell in interactive mode shows no prompt, so we must hold it by hand. 10 | # Every command prepended with other command, which will output only one character ('.') 11 | # When user command leads to no output (for example, 'cd ..'), we get only this character, 12 | # and then we send command to show prompt explicitly. 13 | # No output at all means, that PowerShell needs more input (multiline mode). 14 | # In this case we proceeds sending user input without modifications. 15 | 16 | class PowershellRepl(subprocess_repl.SubprocessRepl): 17 | TYPE = "powershell" 18 | PREPENDER = b"." 19 | 20 | def __init__(self, encoding, **kwds): 21 | if not encoding: 22 | # Detect encoding 23 | chcp = os.popen('chcp') 24 | chcp_encoding = re.match(r'[^\d]+(\d+)', chcp.read()) 25 | if not chcp_encoding: 26 | raise LookupError("Can't detect encoding from chcp") 27 | encoding = "cp" + chcp_encoding.groups()[0] 28 | print(encoding) 29 | 30 | super(PowershellRepl, self).__init__(encoding, **kwds) 31 | 32 | # Using this to detect whether PowerShell returns some output or it needs more input 33 | # PowerShell in interactive mode doesn't show prompt, so we must hold it by hand 34 | # It's a hack and, for example, we can send 'Write-Host "" -NoNewLine' with no output, but in outhr cases it may work well 35 | self.got_output = True 36 | self.multiline = False 37 | 38 | self.prompt() 39 | 40 | def read_bytes(self): 41 | # this is windows specific problem, that you cannot tell if there 42 | # are more bytes ready, so we read only 1 at a times 43 | 44 | result = super(PowershellRepl, self).read_bytes() 45 | 46 | # Consumes output (it must be equal to PREPENDER) 47 | if result and not self.got_output: 48 | self.got_output = True 49 | self.multiline = False 50 | self.prompt() 51 | # Don't return PREPENDER, read another input 52 | return self.read_bytes() 53 | 54 | return result 55 | 56 | def write_bytes(self, bytes): 57 | # Drop flag on new input 58 | self.got_output = False 59 | if not self.multiline: 60 | # Turn multiline mode on, it will be turned off, when PowerShell returns some output 61 | self.multiline = True 62 | self.prepend() 63 | self.do_write(bytes) 64 | 65 | def do_write(self, bytes): 66 | super(PowershellRepl, self).write_bytes(bytes) 67 | 68 | def prompt(self): 69 | """ Sends command to get prompt """ 70 | self.do_write(b'Write-Host ("PS " + (gl).Path + "> ") -NoNewline\n') 71 | 72 | def prepend(self): 73 | """ Command to prepend every output with special mark to detect multiline mode """ 74 | self.do_write(b'Write-Host "' + PowershellRepl.PREPENDER + b'" -NoNewLine; ') 75 | -------------------------------------------------------------------------------- /messages/2.0.0.txt: -------------------------------------------------------------------------------- 1 | Welcome to SublimeREPL 2.0.0 2 | ============================ 3 | 4 | This is the first, official Sublime Text 3 and Sublime Text 2 5 | compatible release. It's been in the works for over 5 months. 6 | 7 | First the bad news: 8 | - during migration persistent history database was changed from 9 | buzhug to PyDBLite. This means you **will have to rebuild** your history. 10 | - Testing release on 6 separate setups (Linux, OSX, Windows with ST2 & ST3) 11 | is becoming a bit time consuming. Recently I test mostly on Linux with 12 | ST3 and occasionally on Windows with ST3 & ST2. 13 | I expect some early bugs, and **count on you** to let me know if something 14 | out of ordinary is happening. Create github issue, send me an email 15 | (github at wuub.net) or reach me on twitter @wuub :) 16 | 17 | 18 | Now the good news. Lots, and I mean LOTS of issues were closed, 19 | in those 5 months. Many of them directly driven by your input. 20 | Here's a condensed changelog, if you want to learn more 21 | feel free to visit 22 | - https://github.com/wuub/SublimeREPL/issues 23 | 24 | 25 | - NEW: Compatibility with Sublime Text 3 and Sublime Text 2 with single codebase 26 | - NEW: documentation improvements 27 | - NEW: 'Restart' command in context menu (even with ghost views after full ST restart) 28 | - NEW: option to open REPLs in next view group (e.g. side-by-side) 29 | - NEW: add option to show evaluated code (#106 and #84) 30 | - BUGFIX: huge output will no longer cause Sublime to become unresponsive (#23... wow :)) 31 | - BUGFIX: closing bracket are now removed automatically (ST3 only, #182) 32 | - NEW: hanlde cases when external_id differs from source.x (think: source.lisp -> scheme repl) (#161, #165 and #167)w 33 | - NEW: [Python] iPython on Windows 34 | - NEW: [Python] automatically remove "#! coding: ..." comments from evaluated code (#187) 35 | - NEW: [Python] iPython plot() support (qt, wx, *not* inline!) 36 | - BUGFIX: [Python] fix pager in IPython (#170) 37 | - BUGFIX: [Python] ipython pager broken on windows (#141) 38 | 39 | - NEW: [Ruby] Pry autocomplete support 40 | - BUGFIX: [Ruby] REPL does not eval at top level (#194) 41 | 42 | - NEW: [Haskell] automatic let binding injection for top level functions 43 | - NEW: [Haskell] let now support top level functions with any kind of parameterization 44 | - BUGFIX: [Haskell] typo in SublimeiHaskellRepl.write(), Code called wrong superclass 45 | - NEW: [Haskell] cabal/cabal-dev depending on SublimeHaskell settings 46 | 47 | - NEW: ClojureScript REPLs 48 | - NEW: Rails REPL 49 | - NEW: Knitr support in R REPL (#165) 50 | - NEW: Maxima REPL 51 | - NEW: Racket REPL 52 | - NEW: Petite Chez Scheme REPL 53 | - REMOVED: Execnet REPL (for now, waiting for community input, anyone uses this?) 54 | 55 | - NEW: change persistent history db from buzhug to PyDbLite (py3) 56 | - BUGFIX: repl could become unresponsive after code evaluation (#159) 57 | - BUGFIX: traceback in is_visible() on context menu 58 | - BUGFIX: AttributeError in update_view_loop 59 | - BUGFIX: fix enter handling with "auto_complete_commit_on_tab": true 60 | - BUGFIX: [F#] The mono command for F# interactive is fsharpi. 61 | - BUGFIX [PowerShell] update pattern for chcp_encoding detection -------------------------------------------------------------------------------- /repls/execnet_repl.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from . import repl 3 | from queue import Queue 4 | import sys 5 | import execnet 6 | 7 | REMOTE_CODE = """ 8 | from __future__ import with_statement 9 | from __future__ import division 10 | from __future__ import absolute_import 11 | #if '{activate_file}': 12 | # execfile('{activate_file}', dict(__file__='{activate_file}')) 13 | 14 | import code 15 | import sys 16 | import time 17 | import contextlib 18 | import threading 19 | try: 20 | from Queue import Queue 21 | except ImportError: 22 | from queue import Queue # py3 23 | 24 | class ChannelOut(object): 25 | def write(self, data): 26 | channel.send(data) 27 | def flush(self): 28 | pass 29 | 30 | @contextlib.contextmanager 31 | def redirect_stdio(): 32 | orig = (sys.stdout, sys.stderr) 33 | sys.stdout = sys.stderr = ChannelOut() 34 | yield 35 | (sys.stdout, sys.stderr) = orig 36 | 37 | class InterceptingConsole(code.InteractiveConsole): 38 | PS1 = "{ps1}" 39 | PS2 = "... " 40 | def __init__(self): 41 | code.InteractiveConsole.__init__(self) 42 | self.input = Queue() 43 | self.output = channel 44 | self.output.send(self.PS1) 45 | 46 | def write(self, data): 47 | self.output.send(data) 48 | 49 | def push(self, line): 50 | with redirect_stdio(): 51 | more = code.InteractiveConsole.push(self, line) 52 | self.output.send(self.PS2 if more else self.PS1) 53 | return more 54 | 55 | def run(self): 56 | while True: 57 | line = self.input.get() 58 | if line is None: 59 | break 60 | self.push(line) 61 | 62 | 63 | ic = InterceptingConsole() 64 | _thread = threading.Thread(target=ic.run) 65 | _thread.start() 66 | 67 | channel.setcallback(ic.input.put, endmarker=None) 68 | 69 | while not channel.isclosed(): 70 | time.sleep(1.0) 71 | """ 72 | 73 | 74 | class ExecnetRepl(repl.Repl): 75 | TYPE = "execnet_repl" 76 | 77 | def __init__(self, encoding, connection_string=None, activate_file="", ps1=">>> "): 78 | super(ExecnetRepl, self).__init__(encoding, "python", "\n", False) 79 | self._connections_string = connection_string 80 | self._ps1 = ps1 81 | self._gw = execnet.makegateway(connection_string) 82 | remote_code = REMOTE_CODE.format(ps1=ps1, activate_file=activate_file) 83 | self._channel = self._gw.remote_exec(remote_code) 84 | self.output = Queue() 85 | self._channel.setcallback(self.output.put, endmarker=None) 86 | self._alive = True 87 | self._killed = False 88 | 89 | def name(self): 90 | return "execnet " + self._ps1.split()[0] 91 | 92 | def is_alive(self): 93 | return self._alive 94 | 95 | def write_bytes(self, bytes): 96 | if self._channel.isclosed(): 97 | self._alive = False 98 | else: 99 | self._channel.send(bytes) 100 | 101 | def read_bytes(self): 102 | bytes = self.output.get() 103 | if bytes is None: 104 | self._gw.exit() 105 | else: 106 | return bytes 107 | 108 | def kill(self): 109 | self._killed = True 110 | self._channel.close() 111 | self._gw.exit() 112 | -------------------------------------------------------------------------------- /config/Python/ipy_repl.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | import socket 5 | import threading 6 | 7 | activate_this = os.environ.get("SUBLIMEREPL_ACTIVATE_THIS", None) 8 | 9 | # turn off pager 10 | os.environ['TERM'] = 'emacs' 11 | 12 | if activate_this: 13 | with open(activate_this, "r") as f: 14 | exec(f.read(), {"__file__": activate_this}) 15 | 16 | try: 17 | import IPython 18 | IPYTHON = True 19 | except ImportError: 20 | IPYTHON = False 21 | 22 | if not IPYTHON: 23 | # for virtualenvs w/o IPython 24 | import code 25 | code.InteractiveConsole().interact() 26 | 27 | from IPython.config.loader import Config 28 | 29 | editor = "subl -w" 30 | 31 | cfg = Config() 32 | cfg.InteractiveShell.use_readline = False 33 | cfg.InteractiveShell.autoindent = False 34 | cfg.InteractiveShell.colors = "NoColor" 35 | cfg.InteractiveShell.editor = os.environ.get("SUBLIMEREPL_EDITOR", editor) 36 | 37 | try: 38 | # IPython 1.0.0 39 | from IPython.terminal.console.app import ZMQTerminalIPythonApp 40 | 41 | def kernel_client(zmq_shell): 42 | return zmq_shell.kernel_client 43 | except ImportError: 44 | # Older IPythons 45 | from IPython.frontend.terminal.console.app import ZMQTerminalIPythonApp 46 | 47 | def kernel_client(zmq_shell): 48 | return zmq_shell.kernel_manager 49 | 50 | 51 | embedded_shell = ZMQTerminalIPythonApp(config=cfg, user_ns={}) 52 | embedded_shell.initialize() 53 | 54 | if os.name == "nt": 55 | # OMG what a fugly hack 56 | import IPython.utils.io as io 57 | io.stdout = io.IOStream(sys.__stdout__, fallback=io.devnull) 58 | io.stderr = io.IOStream(sys.__stderr__, fallback=io.devnull) 59 | embedded_shell.shell.show_banner() # ... my eyes, oh my eyes.. 60 | 61 | 62 | ac_port = int(os.environ.get("SUBLIMEREPL_AC_PORT", "0")) 63 | ac_ip = os.environ.get("SUBLIMEREPL_AC_IP", "127.0.0.1") 64 | if ac_port: 65 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 66 | s.connect((ac_ip, ac_port)) 67 | 68 | 69 | def read_netstring(s): 70 | size = 0 71 | while True: 72 | ch = s.recv(1) 73 | if ch == b':': 74 | break 75 | size = size * 10 + int(ch) 76 | msg = b"" 77 | while size != 0: 78 | msg += s.recv(size) 79 | size -= len(msg) 80 | ch = s.recv(1) 81 | assert ch == b',' 82 | return msg 83 | 84 | 85 | def send_netstring(sock, msg): 86 | payload = b"".join([str(len(msg)).encode("ascii"), b':', msg.encode("utf-8"), b',']) 87 | sock.sendall(payload) 88 | 89 | 90 | def complete(zmq_shell, req): 91 | kc = kernel_client(zmq_shell) 92 | msg_id = kc.shell_channel.complete(**req) 93 | msg = kc.shell_channel.get_msg(timeout=10) 94 | if msg['parent_header']['msg_id'] == msg_id: 95 | return msg["content"]["matches"] 96 | return [] 97 | 98 | 99 | def handle(): 100 | while True: 101 | msg = read_netstring(s).decode("utf-8") 102 | try: 103 | req = json.loads(msg) 104 | completions = complete(embedded_shell, req) 105 | result = (req["text"], completions) 106 | res = json.dumps(result) 107 | send_netstring(s, res) 108 | except Exception: 109 | send_netstring(s, "[]") 110 | 111 | if ac_port: 112 | t = threading.Thread(target=handle) 113 | t.start() 114 | 115 | embedded_shell.start() 116 | 117 | if ac_port: 118 | s.close() 119 | -------------------------------------------------------------------------------- /repls/repl.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2011, Wojciech Bederski (wuub.net) 3 | # All rights reserved. 4 | # See LICENSE.txt for details. 5 | 6 | from uuid import uuid4 7 | from codecs import getincrementaldecoder, getencoder 8 | 9 | 10 | class NoReplError(LookupError): 11 | """Looking for Repl subclass failed""" 12 | pass 13 | 14 | class Repl(object): 15 | """Class that represents a process that is being executed. 16 | For example this can be python, bash or a telnet session""" 17 | 18 | TYPE = "" 19 | 20 | @classmethod 21 | def subclass(cls, type): 22 | """Returns subclass of Repl of given type eq. SubprocessRepl""" 23 | todo = [cls] 24 | seen = set() 25 | while True: 26 | if not todo: 27 | raise NoReplError 28 | cur = todo.pop() 29 | if cur in seen: 30 | continue 31 | if cur.TYPE == type: 32 | return cur 33 | todo.extend(cur.__subclasses__()) 34 | 35 | def __init__(self, encoding, external_id=None, cmd_postfix="\n", suppress_echo=False, 36 | additional_scopes=None, apiv2=False): 37 | self.id = uuid4().hex 38 | self._encoding = encoding 39 | self.decoder = getincrementaldecoder(self._encoding)() 40 | self.encoder = getencoder(encoding) 41 | self.external_id = external_id 42 | self.cmd_postfix = cmd_postfix 43 | self.suppress_echo = suppress_echo 44 | self.additional_scopes = additional_scopes or [] 45 | self.apiv2 = apiv2 46 | 47 | def autocomplete_available(self): 48 | return False 49 | 50 | def autocomplete_completions(self, whole_line, pos_in_line, prefix, whole_prefix, locations): 51 | raise NotImplementedError 52 | 53 | def allow_restarts(self): 54 | """Override if for some reason restart logic should not be 55 | used for this REPL""" 56 | return True 57 | 58 | def close(self): 59 | if self.is_alive(): 60 | self.kill() 61 | 62 | def name(self): 63 | """Returns name of this repl that should be used as a filename""" 64 | return NotImplementedError 65 | 66 | def is_alive(self): 67 | """ Returns true if the undelying process is stil working""" 68 | raise NotImplementedError 69 | 70 | def write_bytes(self, bytes): 71 | raise NotImplementedError 72 | 73 | def read_bytes(self): 74 | """Reads at lest one byte of Repl output. Returns None if output died. 75 | Can block!!!""" 76 | raise NotImplementedError 77 | 78 | def kill(self): 79 | """Kills the underlying repl""" 80 | raise NotImplementedError 81 | 82 | def write(self, command): 83 | """Encodes and evaluates a given command""" 84 | (bytes, how_many) = self.encoder(command) 85 | return self.write_bytes(bytes) 86 | 87 | def reset_decoder(self): 88 | self.decoder = getincrementaldecoder(self._encoding)() 89 | 90 | def read(self): 91 | """Reads at least one decoded char of output""" 92 | while True: 93 | bs = self.read_bytes() 94 | if not bs: 95 | return None 96 | try: 97 | output = self.decoder.decode(bs) 98 | except Exception as e: 99 | output = "■" 100 | self.reset_decoder() 101 | if output: 102 | return output 103 | -------------------------------------------------------------------------------- /repls/sublimehaskell_repl.py: -------------------------------------------------------------------------------- 1 | import re 2 | import os 3 | import sublime 4 | 5 | from .subprocess_repl import SubprocessRepl 6 | 7 | def get_settings(): 8 | return sublime.load_settings("SublimeHaskell.sublime-settings") 9 | 10 | def get_setting(key, default=None): 11 | "This should be used only from main thread" 12 | # Get setting 13 | return get_settings().get(key, default) 14 | 15 | def ghci_package_db(): 16 | dev = get_setting('use_cabal_dev') 17 | box = get_setting('cabal_dev_sandbox') 18 | if dev and box: 19 | package_conf = (filter(lambda x: re.match('packages-(.*)\.conf', x), os.listdir(box)) + [None])[0] 20 | if package_conf: 21 | return os.path.join(box, package_conf) 22 | return None 23 | 24 | def ghci_append_package_db(cmd): 25 | package_conf = ghci_package_db() 26 | if package_conf: 27 | cmd.extend(['-package-db', package_conf]) 28 | return cmd 29 | 30 | def ghci_get_min_whitespace_prefix(lines): 31 | line_spaces = [len(line) - len(line.lstrip()) for line in lines] 32 | if not line_spaces: 33 | return 0 34 | min_spaces = min(line_spaces) 35 | return min_spaces 36 | 37 | def ghci_inject_let(lines): 38 | fixed_lines = [line for line in lines if not line.isspace()] 39 | 40 | letprefix = "let " 41 | spaceprefix = " " 42 | 43 | # matches eg. "func x y z =" 44 | # must start lowercase at start of line 45 | # remaining chars must be upper or lowercase letters, numbers, _ or ' 46 | if fixed_lines and (not fixed_lines[0].startswith("let ")) and re.search("\A([a-z](\w|['_])*[ ]).*[=][ ]", lines[0]): 47 | fixed_lines[0] = letprefix + fixed_lines[0] 48 | fixed_lines[1:] = [spaceprefix + line for line in fixed_lines[1:]] 49 | 50 | return fixed_lines 51 | 52 | def ghci_remove_whitespace(lines): 53 | # remove lines that are completely whitespace 54 | lines = [line for line in lines if not line.isspace()] 55 | 56 | # remove extra whitespace for more flexible block execution 57 | min_spaces = ghci_get_min_whitespace_prefix(lines) 58 | 59 | # remove the minimum number of spaces over all lines from each 60 | fixed_lines = [line[min_spaces:] for line in lines] 61 | return fixed_lines 62 | 63 | def ghci_wrap_multiline_syntax(lines): 64 | # wrap in mutli-line syntax if more than one line 65 | if len(lines) <= 1: 66 | return lines 67 | fixed_lines = [":{" + os.linesep] + lines + [os.linesep + ":}" + os.linesep] 68 | return fixed_lines 69 | 70 | class SublimeHaskellRepl(SubprocessRepl): 71 | TYPE = "sublime_haskell" 72 | 73 | def __init__(self, encoding, cmd=None, **kwds): 74 | super(SublimeHaskellRepl, self).__init__(encoding, cmd=ghci_append_package_db(cmd), **kwds) 75 | 76 | def write(self, command): 77 | setting_multiline = get_setting('format_multiline', True) 78 | setting_trimwhitespace = get_setting('format_trim_whitespace', True) 79 | setting_injectlet = get_setting('format_inject_let', True) 80 | 81 | new_cmd = "" 82 | if command.isspace() or (not setting_multiline and not setting_trimwhitespace): 83 | new_cmd = command 84 | else: 85 | lines = command.splitlines(True) 86 | if setting_trimwhitespace: 87 | lines = ghci_remove_whitespace(lines) 88 | if setting_injectlet: 89 | lines = ghci_inject_let(lines) 90 | if setting_multiline: 91 | lines = ghci_wrap_multiline_syntax(lines) 92 | new_cmd = "".join(lines) 93 | return super(SublimeHaskellRepl, self).write(new_cmd) 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SublimeREPL for SublimeText (2 and 3) 2 | ===================================== 3 | 4 | 5 | [![Stories in Ready](https://badge.waffle.io/wuub/SublimeREPL.png?label=ready)](http://waffle.io/wuub/SublimeREPL) 6 | 7 | If you would like to donate to support SublimeREPL development, you can do so using [GitTip](https://www.gittip.com/wuub/) or [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=4DGEPH7QAVHH6&lc=GB&item_name=SublimeREPL¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted). Someone willing to take care of documentation would also be very welcome :-) 8 | 9 | 10 | Features 11 | -------- 12 | 13 | #### Common 14 | * Run an interpreter (REPL) inside SublimeText2 view/tab. 15 | * Per-language persistent REPL history. 16 | * Easily evaluate code in the running REPL 17 | * Replace your current build system, and use stdin in your programs. 18 | * Rich configuration with platform specific settings, project/file dependent environment variables and sane defaults. 19 | 20 | #### Python 21 | * Launch python in local or remote(1) virtualenv. 22 | * Quickly run selected script or launch PDB. 23 | * Use SublimeText2 Python console with history and multiline input. 24 | 25 | (1) - (ssh, linux/osx only) 26 | 27 | Screenshots 28 | ----------- 29 | #### Running python code in SublimeREPL 30 | ![Running python code in SublimeREPL](http://i.imgur.com/mmYQ6.png) 31 | #### R on Windows 32 | ![R on Windows](http://i.imgur.com/jjsDn.png) 33 | 34 | Videos 35 | ------ 36 | * ![Python & virtualenv over SSH](http://img.youtube.com/vi/zodAqBvKQm0/2.jpg) [Python & virtualenv over SSH](http://youtu.be/zodAqBvKQm0) 37 | * ![SBT integration demo](http://img.youtube.com/vi/1Y7Mr_RJpmU/3.jpg) [SBT integration demo](http://youtu.be/1Y7Mr_RJpmU) 38 | 39 | 40 | Installation 41 | ============ 42 | 43 | 1. Install Package Control. [http://wbond.net/sublime_packages/package_control](http://wbond.net/sublime_packages/package_control) 44 | 2. Install SublimeREPL 45 | 1. `Preferences | Package Control | Package Control: Install Package` 46 | 2. Choose `SublimeREPL` 47 | 3. Restart SublimeText2 48 | 4. Configure `SublimeREPL` (default settings in `Preferences | Package Settings | SublimeREPL | Settings - Default` should be modified in `Preferences | Package Settings | SublimeREPL | Settings - User`, this way they will survive package upgrades! 49 | 50 | Documentation 51 | ============= 52 | 53 | Very basic documentation will soon be available on RTD: [http://sublimerepl.readthedocs.org/](http://sublimerepl.readthedocs.org/) 54 | 55 | #### Getting started 56 | 57 | * Create or open your file with code. 58 | * Menu / Tools / Command Palette (OS X: `⇧⌘P`) 59 | then type "SublimeREPL" and select the approperiate language. 60 | * Menu / View / Layout / Rows: 2 (OS X: `⌥⇧⌘2`). 61 | * Menu / View / Move File to Group / Group 2 (`⌃⇧2`). 62 | 63 | #### Keybindings 64 | 65 | * Evaluate in REPL: 66 | * ctrl+,, s Selection 67 | * ctrl+,, f File 68 | * ctrl+,, l Lines 69 | * ctrl+,, b Block 70 | * Transfer in REPL (just copy, without evaluating it): 71 | * ctrl+shift+,, s Selection 72 | * ctrl+shift+,, f File 73 | * ctrl+shift+,, l Lines 74 | * ctrl+shift+,, b Block 75 | 76 | Note: ctrl+,, f means: press Ctrl and Comma, release all, press F. 77 | 78 | 79 | License and Price 80 | ================= 81 | 82 | Since version 1.2.0 SublimeREPL is licensed under GPL. Previous versions were licensed under BSD. 83 | If you're using SublimeREPL in commercial environment a donation is strongly encouraged ;-) 84 | 85 | Compatibility 86 | ================ 87 | 88 | SublimeREPL is developed against the latest dev build of SublimeText3. 89 | Ubuntu 13.04 is main 90 | -------------------------------------------------------------------------------- /config/Python/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"caption": "Python", 12 | "id": "Python", 13 | 14 | "children":[ 15 | {"command": "repl_open", 16 | "caption": "Python", 17 | "id": "repl_python", 18 | "mnemonic": "P", 19 | "args": { 20 | "type": "subprocess", 21 | "encoding": "utf8", 22 | "cmd": ["python", "-i", "-u"], 23 | "cwd": "$file_path", 24 | "syntax": "Packages/Python/Python.tmLanguage", 25 | "external_id": "python", 26 | "extend_env": {"PYTHONIOENCODING": "utf-8"} 27 | } 28 | }, 29 | {"command": "python_virtualenv_repl", 30 | "id": "python_virtualenv_repl", 31 | "caption": "Python - virtualenv"}, 32 | {"command": "repl_open", 33 | "caption": "Python - PDB current file", 34 | "id": "repl_python_pdb", 35 | "mnemonic": "D", 36 | "args": { 37 | "type": "subprocess", 38 | "encoding": "utf8", 39 | "cmd": ["python", "-i", "-u", "-m", "pdb", "$file_basename"], 40 | "cwd": "$file_path", 41 | "syntax": "Packages/Python/Python.tmLanguage", 42 | "external_id": "python", 43 | "extend_env": {"PYTHONIOENCODING": "utf-8"} 44 | } 45 | }, 46 | {"command": "repl_open", 47 | "caption": "Python - RUN current file", 48 | "id": "repl_python_run", 49 | "mnemonic": "R", 50 | "args": { 51 | "type": "subprocess", 52 | "encoding": "utf8", 53 | "cmd": ["python", "-u", "$file_basename"], 54 | "cwd": "$file_path", 55 | "syntax": "Packages/Python/Python.tmLanguage", 56 | "external_id": "python", 57 | "extend_env": {"PYTHONIOENCODING": "utf-8"} 58 | } 59 | }, 60 | {"command": "repl_open", 61 | "caption": "Python - IPython", 62 | "id": "repl_python_ipython", 63 | "mnemonic": "I", 64 | "args": { 65 | "type": "subprocess", 66 | "encoding": "utf8", 67 | "autocomplete_server": true, 68 | "cmd": { 69 | "osx": ["python", "-u", "${packages}/SublimeREPL/config/Python/ipy_repl.py"], 70 | "linux": ["python", "-u", "${packages}/SublimeREPL/config/Python/ipy_repl.py"], 71 | "windows": ["python", "-u", "${packages}/SublimeREPL/config/Python/ipy_repl.py"] 72 | }, 73 | "cwd": "$file_path", 74 | "syntax": "Packages/Python/Python.tmLanguage", 75 | "external_id": "python", 76 | "extend_env": { 77 | "PYTHONIOENCODING": "utf-8", 78 | "SUBLIMEREPL_EDITOR": "$editor" 79 | } 80 | } 81 | } 82 | ]} 83 | ] 84 | }] 85 | } 86 | ] 87 | -------------------------------------------------------------------------------- /SublimeREPL.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | // default_extend_env are used to augment any environment variables 3 | // that should be visible for all subprocess repls launched within 4 | // SublimeREPL. This is a very good place to add PATH extension 5 | // once "PATH": "{PATH}:/home/username/mylocalinstalls/bin" or whatever 6 | "default_extend_env": {}, 7 | 8 | // Specify whether to move repls to a different Sublime Text group (frame) 9 | // immediately on opening. Setting this to true will simply move it to 10 | // the 'next' group from the one that was in focus when it was opened 11 | // (one down with row layout, one to the right with column and grid 12 | // layout). Alternatively, you can set this to the index of the group in 13 | // which you want all repls to be opened (index 0 being the top-left group). 14 | // Activating this option will NOT automatically change your layout/create 15 | // a new group if it isn't open. 16 | "open_repl_in_group": true, 17 | 18 | // Persistent history is stored per REPL external_id, it means that all python 19 | // REPLS will share history. If you wish you can disable history altogether 20 | "persistent_history_enabled": true, 21 | 22 | // By default SublimeREPL leaves REPL view open once the underlying subprocess 23 | // dies or closes connection. This is useful when the process dies for an unexpected 24 | // reason as it allows you to inspect it output. If you want. Setting this 25 | // to true will cause SublimreREPL to close view once the process died. 26 | "view_auto_close": false, 27 | 28 | // On POSIX system SublimeText launched from GUI does not inherit 29 | // a proper environment. Often leading to problems with finding interpreters 30 | // or not using the ones affected by changes in ~/.profile / *rc files 31 | // This command is used as a workaround, it's launched before any subprocess 32 | // repl starts and it's output is parsed as an environment 33 | "getenv_command": ["/bin/bash", "--login", "-c", "env"], 34 | 35 | // Some terminals output ascii color codes which are not currently supported 36 | // enable this option to filter them out. 37 | "filter_ascii_color_codes": true, 38 | 39 | // Where to look for python virtualenvs 40 | "python_virtualenv_paths": [ 41 | "~/.virtualenvs", // virtualenvwrapper 42 | "~/.venv" // venv.bash https://github.com/wuub/venv 43 | ], 44 | 45 | // Use arrows for history navigation instead of Alt+[P|N]/Ctrl+[P|N] 46 | "history_arrows": true, 47 | 48 | // standard sublime view settings that will be overwritten on each repl view 49 | // this has to be customized as a whole dictionary 50 | "repl_view_settings": { 51 | "translate_tabs_to_spaces": false, 52 | "auto_indent": false, 53 | "smart_indent": false, 54 | "spell_check": false, 55 | "indent_subsequent_lines": false, 56 | "detect_indentation": false, 57 | "auto_complete": true, 58 | "line_numbers": false, 59 | "gutter": false 60 | }, 61 | 62 | // this settings exposes additional variables in repl config files, especially 63 | // those related to sublime projects that are not available through standard API 64 | // WARNING: this will switch your build system back to Automatic each time a REPL 65 | // is started so beware! 66 | "use_build_system_hack": false, 67 | 68 | // IP address used to setup autocomplete server in sublimerepl. 69 | // changing this is usefull when you want to exclude one address 70 | // from proxychains/tsocks routing 71 | "autocomplete_server_ip": "127.0.0.1", 72 | 73 | // Mapping is used, when external_id of REPL does not match 74 | // source.[xxx] scope of syntax definition used to highlight 75 | // files from which text is being transfered. For example octave 76 | // repls use source.matlab syntax files and w/o this mapping text transfer 77 | // will not work 78 | "external_id_mapping": { 79 | "octave": "matlab" 80 | }, 81 | 82 | // If set to true, SublimeREPL will try to append evaluated code to repl 83 | // output before evaluation (e.g. Ctrl+, f) 84 | "show_transferred_text": false, 85 | 86 | // If set to true repl view (tab) that receives text for evaluation will 87 | // be brought to front after text transfer. Note: This will not fire if repl view 88 | // is in the same tab group as the view from which the code is sent. 89 | "focus_view_on_transfer": true 90 | } 91 | -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["up"], "command": "repl_view_previous", 3 | "context": 4 | [ 5 | { "key": "setting.history_arrows", "operator": "equal", "operand": true }, 6 | { "key": "setting.repl", "operator": "equal", "operand": true }, 7 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 8 | ] 9 | }, 10 | { "keys": ["alt+p"], "command": "repl_view_previous", 11 | "context": 12 | [ 13 | { "key": "setting.history_arrows", "operator": "equal", "operand": false }, 14 | { "key": "setting.repl", "operator": "equal", "operand": true } 15 | ] 16 | }, 17 | { "keys": ["down"], "command": "repl_view_next", 18 | "context": 19 | [ 20 | { "key": "setting.history_arrows", "operator": "equal", "operand": true }, 21 | { "key": "setting.repl", "operator": "equal", "operand": true }, 22 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 23 | ] 24 | }, 25 | { "keys": ["alt+n"], "command": "repl_view_next", 26 | "context": 27 | [ 28 | { "key": "setting.history_arrows", "operator": "equal", "operand": false }, 29 | { "key": "setting.repl", "operator": "equal", "operand": true } 30 | ] 31 | }, 32 | { "keys": ["enter"], "command": "repl_enter", "args": {}, 33 | "context": 34 | [ 35 | { "key": "setting.repl", "operator": "equal", "operand": true }, 36 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 37 | ] 38 | }, 39 | { "keys": ["enter"], "command": "repl_enter", "args": {}, 40 | "context": 41 | [ 42 | { "key": "setting.repl", "operator": "equal", "operand": true }, 43 | { "key": "setting.auto_complete_commit_on_tab", "operand": true } 44 | ] 45 | }, 46 | { "keys": ["escape"], "command": "repl_escape", "args": {}, 47 | "context": 48 | [ 49 | { "key": "auto_complete_visible", "operator": "equal", "operand": false }, 50 | { "key": "setting.repl", "operator": "equal", "operand": true } 51 | ] 52 | }, 53 | { "keys": ["backspace"], "command": "repl_backspace", "args": {}, 54 | "context": 55 | [ 56 | { "key": "setting.repl", "operator": "equal", "operand": true }, 57 | { "key": "setting.repl_sublime2", "operator": "equal", "operand": true }, 58 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 59 | ] 60 | }, 61 | { "keys": ["ctrl+backspace"], "command": "repl_ctrl_backspace", "args": {}, 62 | "context": 63 | [ 64 | { "key": "setting.repl", "operator": "equal", "operand": true }, 65 | { "key": "setting.repl_sublime2", "operator": "equal", "operand": true }, 66 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 67 | ] 68 | }, 69 | { "keys": ["left"], "command": "repl_left", "args": {}, 70 | "context": 71 | [ 72 | { "key": "setting.repl", "operator": "equal", "operand": true } 73 | ] 74 | }, 75 | { "keys": ["home"], "command": "repl_home", "args": {}, 76 | "context": 77 | [ 78 | { "key": "setting.repl", "operator": "equal", "operand": true } 79 | ] 80 | }, 81 | { "keys": ["shift+left"], "command": "repl_shift_left", "args": {}, 82 | "context": 83 | [ 84 | { "key": "setting.repl", "operator": "equal", "operand": true } 85 | ] 86 | }, 87 | { "keys": ["shift+home"], "command": "repl_shift_home", "args": {}, 88 | "context": 89 | [ 90 | { "key": "setting.repl", "operator": "equal", "operand": true } 91 | ] 92 | }, 93 | { "keys": ["shift+ctrl+c"], "command": "repl_clear", 94 | "context": 95 | [ 96 | { "key": "setting.repl", "operator": "equal", "operand": true } 97 | ] 98 | }, 99 | 100 | 101 | { "keys": ["ctrl+,", "s"], "command": "repl_transfer_current", "args": {"scope": "selection"}}, 102 | { "keys": ["ctrl+shift+,", "s"], "command": "repl_transfer_current", "args": {"scope": "selection", "action":"view_write"}}, 103 | { "keys": ["ctrl+,", "f"], "command": "repl_transfer_current", "args": {"scope": "file"}}, 104 | { "keys": ["shift+ctrl+,", "f"], "command": "repl_transfer_current", "args": {"scope": "file", "action":"view_write"}}, 105 | { "keys": ["ctrl+,", "l"], "command": "repl_transfer_current", "args": {"scope": "lines"}}, 106 | { "keys": ["shift+ctrl+,", "l"], "command": "repl_transfer_current", "args": {"scope": "lines", "action":"view_write"}}, 107 | { "keys": ["ctrl+,", "b"], "command": "repl_transfer_current", "args": {"scope": "block"}}, 108 | { "keys": ["shift+ctrl+,", "b"], "command": "repl_transfer_current", "args": {"scope": "block", "action":"view_write"}} 109 | ] 110 | -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["up"], "command": "repl_view_previous", 3 | "context": 4 | [ 5 | { "key": "setting.history_arrows", "operator": "equal", "operand": true }, 6 | { "key": "setting.repl", "operator": "equal", "operand": true }, 7 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 8 | ] 9 | }, 10 | { "keys": ["alt+p"], "command": "repl_view_previous", 11 | "context": 12 | [ 13 | { "key": "setting.history_arrows", "operator": "equal", "operand": false }, 14 | { "key": "setting.repl", "operator": "equal", "operand": true } 15 | ] 16 | }, 17 | { "keys": ["down"], "command": "repl_view_next", 18 | "context": 19 | [ 20 | { "key": "setting.history_arrows", "operator": "equal", "operand": true }, 21 | { "key": "setting.repl", "operator": "equal", "operand": true }, 22 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 23 | ] 24 | }, 25 | { "keys": ["alt+n"], "command": "repl_view_next", 26 | "context": 27 | [ 28 | { "key": "setting.history_arrows", "operator": "equal", "operand": false }, 29 | { "key": "setting.repl", "operator": "equal", "operand": true } 30 | ] 31 | }, 32 | { "keys": ["enter"], "command": "repl_enter", "args": {}, 33 | "context": 34 | [ 35 | { "key": "setting.repl", "operator": "equal", "operand": true }, 36 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 37 | ] 38 | }, 39 | { "keys": ["enter"], "command": "repl_enter", "args": {}, 40 | "context": 41 | [ 42 | { "key": "setting.repl", "operator": "equal", "operand": true }, 43 | { "key": "setting.auto_complete_commit_on_tab", "operand": true } 44 | ] 45 | }, 46 | { "keys": ["escape"], "command": "repl_escape", "args": {}, 47 | "context": 48 | [ 49 | { "key": "auto_complete_visible", "operator": "equal", "operand": false }, 50 | { "key": "setting.repl", "operator": "equal", "operand": true } 51 | ] 52 | }, 53 | { "keys": ["backspace"], "command": "repl_backspace", "args": {}, 54 | "context": 55 | [ 56 | { "key": "setting.repl", "operator": "equal", "operand": true }, 57 | { "key": "setting.repl_sublime2", "operator": "equal", "operand": true }, 58 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 59 | ] 60 | }, 61 | { "keys": ["ctrl+backspace"], "command": "repl_ctrl_backspace", "args": {}, 62 | "context": 63 | [ 64 | { "key": "setting.repl", "operator": "equal", "operand": true }, 65 | { "key": "setting.repl_sublime2", "operator": "equal", "operand": true }, 66 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 67 | ] 68 | }, 69 | { "keys": ["left"], "command": "repl_left", "args": {}, 70 | "context": 71 | [ 72 | { "key": "setting.repl", "operator": "equal", "operand": true } 73 | ] 74 | }, 75 | { "keys": ["home"], "command": "repl_home", "args": {}, 76 | "context": 77 | [ 78 | { "key": "setting.repl", "operator": "equal", "operand": true } 79 | ] 80 | }, 81 | { "keys": ["shift+left"], "command": "repl_shift_left", "args": {}, 82 | "context": 83 | [ 84 | { "key": "setting.repl", "operator": "equal", "operand": true } 85 | ] 86 | }, 87 | { "keys": ["shift+home"], "command": "repl_shift_home", "args": {}, 88 | "context": 89 | [ 90 | { "key": "setting.repl", "operator": "equal", "operand": true } 91 | ] 92 | }, 93 | { "keys": ["ctrl+l"], "command": "repl_clear", 94 | "context": 95 | [ 96 | { "key": "setting.repl", "operator": "equal", "operand": true } 97 | ] 98 | }, 99 | { "keys": ["shift+ctrl+c"], "command": "subprocess_repl_send_signal", "args": {"signal": 2}, // sigint 100 | "context": 101 | [ 102 | { "key": "setting.repl", "operator": "equal", "operand": true } 103 | ] 104 | }, 105 | 106 | 107 | { "keys": ["ctrl+,", "s"], "command": "repl_transfer_current", "args": {"scope": "selection"}}, 108 | { "keys": ["ctrl+shift+,", "s"], "command": "repl_transfer_current", "args": {"scope": "selection", "action":"view_write"}}, 109 | { "keys": ["ctrl+,", "f"], "command": "repl_transfer_current", "args": {"scope": "file"}}, 110 | { "keys": ["shift+ctrl+,", "f"], "command": "repl_transfer_current", "args": {"scope": "file", "action":"view_write"}}, 111 | { "keys": ["ctrl+,", "l"], "command": "repl_transfer_current", "args": {"scope": "lines"}}, 112 | { "keys": ["shift+ctrl+,", "l"], "command": "repl_transfer_current", "args": {"scope": "lines", "action":"view_write"}}, 113 | { "keys": ["ctrl+,", "b"], "command": "repl_transfer_current", "args": {"scope": "block"}}, 114 | { "keys": ["shift+ctrl+,", "b"], "command": "repl_transfer_current", "args": {"scope": "block", "action":"view_write"}} 115 | ] 116 | 117 | -------------------------------------------------------------------------------- /config/Io/repl.io: -------------------------------------------------------------------------------- 1 | # This code is modified Z_CLI.io from https://github.com/stevedekorte/io/blob/master/libs/iovm/io/Z_CLI.io 2 | Locals removeSlot("doFile") 3 | 4 | DummyLine := File standardInput do( 5 | readLine := method(prompt, 6 | if(prompt, prompt print; File flush) 7 | resend 8 | ) 9 | ) 10 | 11 | CLI := Object clone do( 12 | prompt ::= "Io> " 13 | outPrompt ::= "==> " 14 | continuedLinePrompt ::= "... " 15 | 16 | isRunning ::= true # Get rid of this ... 17 | commandLineLabel ::= "Command Line" # and this? 18 | 19 | context ::= lazySlot( 20 | Lobby do( 21 | # Python-style underscore, stores the result of the previous computation. 22 | # Example: 23 | # Io> 1 + 1 24 | # ==> 2 25 | # Io> _ == 2 26 | # ==> true 27 | _ ::= nil 28 | 29 | exit := method(CLI stop) 30 | ) 31 | ) 32 | 33 | lineReader := lazySlot( 34 | # This might look as a `hack`, but why not use stdin as the default 35 | # reader, since it shares the same interface with Read(Edit)Line, 36 | # i.e. readLine. 37 | reader := DummyLine 38 | 39 | # Trying to use GNU ReadLine as the default line reader, falling 40 | # back to EditLine, if the attempt failed. 41 | try(reader := ReadLine) catch(Exception, 42 | try(reader := EditLine) 43 | ) 44 | reader 45 | ) 46 | 47 | # A list of error messages for the errors we understand. 48 | knownErrors := lazySlot( 49 | list("(", "[", "{", "\"\"\"", "(x,") map(error, 50 | self errorMessage(try(error asMessage) error) 51 | ) 52 | ) 53 | 54 | errorMessage := method(error, error beforeSeq(" on line")) 55 | 56 | doFile := method(path, 57 | System launchPath = if(Path isPathAbsolute(path), 58 | path 59 | , 60 | System launchPath asMutable appendPathSeq(path) 61 | ) pathComponent 62 | 63 | System launchScript = path 64 | 65 | context doFile(path) 66 | ) 67 | 68 | doLine := method(lineAsMessage, 69 | # Execute the line and report any exceptions which happened. 70 | executionError := try(result := context doMessage(lineAsMessage)) 71 | if(executionError, 72 | executionError showStack 73 | , 74 | # Write out the command's result to stdout; nothing is written 75 | # if the CLI is terminated, this condition is satisfied, only 76 | # when CLI exit() was called. 77 | if(isRunning, 78 | context set_(getSlot("result")) 79 | writeCommandResult(getSlot("result"))) 80 | ) 81 | ) 82 | 83 | doIorc := method( 84 | # Note: Probably won't work on Windows, since it uses %HOMEPATH% 85 | # and %HOMEDRIVE% pair to indentify user's home directory. 86 | home := System getEnvironmentVariable("HOME") 87 | if(home, 88 | path := Path with(home, ".iorc") 89 | if(File with(path) exists, 90 | context doFile(path) 91 | ) 92 | ) 93 | ) 94 | 95 | writeWelcomeBanner := method("Io #{System version}" interpolate println) 96 | writeCommandResult := method(result, 97 | outPrompt print 98 | 99 | if(exc := try(getSlot("result") asString println), 100 | "" println 101 | exc showStack 102 | ) 103 | ) 104 | 105 | stop := method(setIsRunning(false)) 106 | 107 | interactive := method( 108 | # Start with the default prompt. The prompt is changed for continued lines, 109 | # and errors. 110 | prompt := self prompt 111 | line := "" 112 | # If there are unmatched (, {, [ or the command ends with a \ then we'll 113 | # need to read multiple lines. 114 | loop( 115 | # Write out prompt and read line. 116 | if(nextLine := lineReader readLine(prompt), 117 | # Add what we read to the line we've been building up 118 | line = line .. nextLine 119 | , 120 | # Note: readLine method returns nil if ^D was pressed. 121 | context exit 122 | "\n" print # Fixing the newline issue. 123 | ) 124 | 125 | compileError := try( 126 | lineAsMessage := line asMessage setLabel(commandLineLabel) 127 | ) 128 | 129 | if(compileError, 130 | # Not sure that, displaying a different notification for 131 | # each error actually makes sense. 132 | if(nextLine size > 0 and errorMessage(compileError error) in(knownErrors), 133 | prompt = continuedLinePrompt 134 | continue 135 | ) 136 | # If the error can't be fixed by continuing the line - report it. 137 | compileError showStack 138 | , 139 | doLine(lineAsMessage) 140 | ) 141 | 142 | return if(isRunning, interactive, nil) 143 | ) 144 | ) 145 | ) 146 | 147 | CLI interactive 148 | -------------------------------------------------------------------------------- /config/CommonLisp/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "children": 5 | [{ 6 | "caption": "SublimeREPL", 7 | "mnemonic": "R", 8 | "id": "SublimeREPL", 9 | "children": 10 | [ 11 | {"caption": "Common Lisp", 12 | "id": "CommonLisp", 13 | 14 | "children":[ 15 | {"command": "repl_open", 16 | "caption": "Clozure CL", 17 | "id": "repl_ccl", 18 | "mnemonic": "C", 19 | "args": { 20 | "type": "subprocess", 21 | "encoding": "utf8", 22 | "external_id": "lisp", 23 | "cmd": ["ccl"], 24 | "soft_quit": "\n(ccl:quit)\n", 25 | "cwd": "$folder", 26 | "cmd_postfix": "\n", 27 | "syntax": "Packages/Lisp/Lisp.tmLanguage" 28 | } 29 | }, 30 | {"command": "repl_open", 31 | "caption": "SBCL", 32 | "id": "repl_sbcl", 33 | "mnemonic": "S", 34 | "args": { 35 | "type": "subprocess", 36 | "encoding": "utf8", 37 | "external_id": "lisp", 38 | "cmd": ["sbcl"], 39 | "soft_quit": "\n(sb-ext:exit)\n", 40 | "cwd": "$folder", 41 | "cmd_postfix": "\n", 42 | "syntax": "Packages/Lisp/Lisp.tmLanguage" 43 | } 44 | }, 45 | {"command": "repl_open", 46 | "caption": "GNU Clisp", 47 | "id": "repl_clisp", 48 | "mnemonic": "G", 49 | "args": { 50 | "type": "subprocess", 51 | "encoding": "utf8", 52 | "external_id": "lisp", 53 | "cmd": ["clisp", "-disable-readline"], 54 | "soft_quit": "\n(ext:quit)\n", 55 | "cwd": "$folder", 56 | "cmd_postfix": "\n", 57 | "syntax": "Packages/Lisp/Lisp.tmLanguage" 58 | } 59 | }, 60 | {"command": "repl_open", 61 | "caption": "Allegro CL", 62 | "id": "repl_allegro", 63 | "mnemonic": "A", 64 | "args": { 65 | "type": "subprocess", 66 | "encoding": "utf8", 67 | "external_id": "lisp", 68 | "cmd": ["alisp"], 69 | "soft_quit": "\n(excl:exit 0 :quiet t)\n", 70 | "cwd": "$folder", 71 | "cmd_postfix": "\n", 72 | "syntax": "Packages/Lisp/Lisp.tmLanguage" 73 | } 74 | }, 75 | {"command": "repl_open", 76 | "caption": "ABCL", 77 | "id": "repl_abcl", 78 | "mnemonic": "B", 79 | "args": { 80 | "type": "subprocess", 81 | "encoding": "utf8", 82 | "external_id": "lisp", 83 | "cmd": ["abcl"], 84 | "soft_quit": "\n(ext:exit)\n", 85 | "cwd": "$folder", 86 | "cmd_postfix": "\n", 87 | "syntax": "Packages/Lisp/Lisp.tmLanguage" 88 | } 89 | }, 90 | {"command": "repl_open", 91 | "caption": "CMUCL", 92 | "id": "repl_cmucl", 93 | "mnemonic": "M", 94 | "args": { 95 | "type": "subprocess", 96 | "encoding": "utf8", 97 | "external_id": "lisp", 98 | "cmd": ["lisp"], 99 | "soft_quit": "\n(ext::quit)\n", 100 | "cwd": "$folder", 101 | "cmd_postfix": "\n", 102 | "syntax": "Packages/Lisp/Lisp.tmLanguage" 103 | } 104 | }, 105 | {"command": "repl_open", 106 | "caption": "ECL", 107 | "id": "repl_ecl", 108 | "mnemonic": "E", 109 | "args": { 110 | "type": "subprocess", 111 | "encoding": "utf8", 112 | "external_id": "lisp", 113 | "cmd": ["ecl"], 114 | "soft_quit": "\n(ext:quit)\n", 115 | "cwd": "$folder", 116 | "cmd_postfix": "\n", 117 | "syntax": "Packages/Lisp/Lisp.tmLanguage" 118 | } 119 | } 120 | ]} 121 | ] 122 | }] 123 | } 124 | ] 125 | -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["up"], "command": "repl_view_previous", 3 | "context": 4 | [ 5 | { "key": "setting.history_arrows", "operator": "equal", "operand": true }, 6 | { "key": "setting.repl", "operator": "equal", "operand": true }, 7 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 8 | ] 9 | }, 10 | { "keys": ["ctrl+p"], "command": "repl_view_previous", 11 | "context": 12 | [ 13 | { "key": "setting.history_arrows", "operator": "equal", "operand": false }, 14 | { "key": "setting.repl", "operator": "equal", "operand": true } 15 | ] 16 | }, 17 | { "keys": ["down"], "command": "repl_view_next", 18 | "context": 19 | [ 20 | { "key": "setting.history_arrows", "operator": "equal", "operand": true }, 21 | { "key": "setting.repl", "operator": "equal", "operand": true }, 22 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 23 | ] 24 | }, 25 | { "keys": ["ctrl+n"], "command": "repl_view_next", 26 | "context": 27 | [ 28 | { "key": "setting.history_arrows", "operator": "equal", "operand": false }, 29 | { "key": "setting.repl", "operator": "equal", "operand": true } 30 | ] 31 | }, 32 | { "keys": ["enter"], "command": "repl_enter", "args": {}, 33 | "context": 34 | [ 35 | { "key": "setting.repl", "operator": "equal", "operand": true }, 36 | { "key": "auto_complete_visible", "operator": "equal", "operand": false } 37 | ] 38 | }, 39 | { "keys": ["enter"], "command": "repl_enter", "args": {}, 40 | "context": 41 | [ 42 | { "key": "setting.repl", "operator": "equal", "operand": true }, 43 | { "key": "setting.auto_complete_commit_on_tab", "operand": true } 44 | ] 45 | }, 46 | { "keys": ["escape"], "command": "repl_escape", "args": {}, 47 | "context": 48 | [ 49 | { "key": "auto_complete_visible", "operator": "equal", "operand": false }, 50 | { "key": "setting.repl", "operator": "equal", "operand": true } 51 | ] 52 | }, 53 | { "keys": ["backspace"], "command": "repl_backspace", "args": {}, 54 | "context": 55 | [ 56 | { "key": "setting.repl", "operator": "equal", "operand": true }, 57 | { "key": "setting.repl_sublime2", "operator": "equal", "operand": true }, 58 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 59 | ] 60 | }, 61 | { "keys": ["ctrl+backspace"], "command": "repl_ctrl_backspace", "args": {}, 62 | "context": 63 | [ 64 | { "key": "setting.repl", "operator": "equal", "operand": true }, 65 | { "key": "setting.repl_sublime2", "operator": "equal", "operand": true }, 66 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 67 | ] 68 | }, 69 | { "keys": ["super+backspace"], "command": "repl_super_backspace", "args": {}, 70 | "context": 71 | [ 72 | { "key": "setting.repl", "operator": "equal", "operand": true }, 73 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 74 | ] 75 | }, 76 | { "keys": ["alt+backspace"], "command": "repl_ctrl_backspace", "args": {}, 77 | "context": 78 | [ 79 | { "key": "setting.repl", "operator": "equal", "operand": true }, 80 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true } 81 | ] 82 | }, 83 | { "keys": ["left"], "command": "repl_left", "args": {}, 84 | "context": 85 | [ 86 | { "key": "setting.repl", "operator": "equal", "operand": true } 87 | ] 88 | }, 89 | { "keys": ["home"], "command": "repl_home", "args": {}, 90 | "context": 91 | [ 92 | { "key": "setting.repl", "operator": "equal", "operand": true } 93 | ] 94 | }, 95 | { "keys": ["ctrl+a"], "command": "repl_home", "args": {}, 96 | "context": 97 | [ 98 | { "key": "setting.repl", "operator": "equal", "operand": true } 99 | ] 100 | }, 101 | { "keys": ["shift+left"], "command": "repl_shift_left", "args": {}, 102 | "context": 103 | [ 104 | { "key": "setting.repl", "operator": "equal", "operand": true } 105 | ] 106 | }, 107 | { "keys": ["shift+home"], "command": "repl_shift_home", "args": {}, 108 | "context": 109 | [ 110 | { "key": "setting.repl", "operator": "equal", "operand": true } 111 | ] 112 | }, 113 | { "keys": ["ctrl+l"], "command": "repl_clear", 114 | "context": 115 | [ 116 | { "key": "setting.repl", "operator": "equal", "operand": true } 117 | ] 118 | }, 119 | { "keys": ["shift+ctrl+c"], "command": "subprocess_repl_send_signal", "args": {"signal": 2}, // sigint 120 | "context": 121 | [ 122 | { "key": "setting.repl", "operator": "equal", "operand": true } 123 | ] 124 | }, 125 | 126 | 127 | { "keys": ["ctrl+,", "s"], "command": "repl_transfer_current", "args": {"scope": "selection"}}, 128 | { "keys": ["ctrl+shift+,", "s"], "command": "repl_transfer_current", "args": {"scope": "selection", "action":"view_write"}}, 129 | { "keys": ["ctrl+,", "f"], "command": "repl_transfer_current", "args": {"scope": "file"}}, 130 | { "keys": ["shift+ctrl+,", "f"], "command": "repl_transfer_current", "args": {"scope": "file", "action":"view_write"}}, 131 | { "keys": ["ctrl+,", "l"], "command": "repl_transfer_current", "args": {"scope": "lines"}}, 132 | { "keys": ["shift+ctrl+,", "l"], "command": "repl_transfer_current", "args": {"scope": "lines", "action":"view_write"}}, 133 | { "keys": ["ctrl+,", "b"], "command": "repl_transfer_current", "args": {"scope": "block"}}, 134 | { "keys": ["shift+ctrl+,", "b"], "command": "repl_transfer_current", "args": {"scope": "block", "action":"view_write"}} 135 | ] 136 | -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. linkcheck to check all external links for integrity 37 | echo. doctest to run all doctests embedded in the documentation if enabled 38 | goto end 39 | ) 40 | 41 | if "%1" == "clean" ( 42 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 43 | del /q /s %BUILDDIR%\* 44 | goto end 45 | ) 46 | 47 | if "%1" == "html" ( 48 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 49 | if errorlevel 1 exit /b 1 50 | echo. 51 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 52 | goto end 53 | ) 54 | 55 | if "%1" == "dirhtml" ( 56 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 57 | if errorlevel 1 exit /b 1 58 | echo. 59 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 60 | goto end 61 | ) 62 | 63 | if "%1" == "singlehtml" ( 64 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 68 | goto end 69 | ) 70 | 71 | if "%1" == "pickle" ( 72 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished; now you can process the pickle files. 76 | goto end 77 | ) 78 | 79 | if "%1" == "json" ( 80 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished; now you can process the JSON files. 84 | goto end 85 | ) 86 | 87 | if "%1" == "htmlhelp" ( 88 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can run HTML Help Workshop with the ^ 92 | .hhp project file in %BUILDDIR%/htmlhelp. 93 | goto end 94 | ) 95 | 96 | if "%1" == "qthelp" ( 97 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 98 | if errorlevel 1 exit /b 1 99 | echo. 100 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 101 | .qhcp project file in %BUILDDIR%/qthelp, like this: 102 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\SublimeREPL.qhcp 103 | echo.To view the help file: 104 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\SublimeREPL.ghc 105 | goto end 106 | ) 107 | 108 | if "%1" == "devhelp" ( 109 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 110 | if errorlevel 1 exit /b 1 111 | echo. 112 | echo.Build finished. 113 | goto end 114 | ) 115 | 116 | if "%1" == "epub" ( 117 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 118 | if errorlevel 1 exit /b 1 119 | echo. 120 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 121 | goto end 122 | ) 123 | 124 | if "%1" == "latex" ( 125 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 129 | goto end 130 | ) 131 | 132 | if "%1" == "text" ( 133 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The text files are in %BUILDDIR%/text. 137 | goto end 138 | ) 139 | 140 | if "%1" == "man" ( 141 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 145 | goto end 146 | ) 147 | 148 | if "%1" == "texinfo" ( 149 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 150 | if errorlevel 1 exit /b 1 151 | echo. 152 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 153 | goto end 154 | ) 155 | 156 | if "%1" == "gettext" ( 157 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 158 | if errorlevel 1 exit /b 1 159 | echo. 160 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 161 | goto end 162 | ) 163 | 164 | if "%1" == "changes" ( 165 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 166 | if errorlevel 1 exit /b 1 167 | echo. 168 | echo.The overview file is in %BUILDDIR%/changes. 169 | goto end 170 | ) 171 | 172 | if "%1" == "linkcheck" ( 173 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 174 | if errorlevel 1 exit /b 1 175 | echo. 176 | echo.Link check complete; look for any errors in the above output ^ 177 | or in %BUILDDIR%/linkcheck/output.txt. 178 | goto end 179 | ) 180 | 181 | if "%1" == "doctest" ( 182 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 183 | if errorlevel 1 exit /b 1 184 | echo. 185 | echo.Testing of doctests in the sources finished, look at the ^ 186 | results in %BUILDDIR%/doctest/output.txt. 187 | goto end 188 | ) 189 | 190 | :end 191 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SublimeREPL.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SublimeREPL.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/SublimeREPL" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SublimeREPL" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /repls/killableprocess/qijo.py: -------------------------------------------------------------------------------- 1 | from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFUNCTYPE, addressof, c_size_t, c_ulong 2 | from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LARGE_INTEGER 3 | 4 | LPVOID = c_void_p 5 | LPDWORD = POINTER(DWORD) 6 | SIZE_T = c_size_t 7 | ULONG_PTR = POINTER(c_ulong) 8 | 9 | # A ULONGLONG is a 64-bit unsigned integer. 10 | # Thus there are 8 bytes in a ULONGLONG. 11 | # XXX why not import c_ulonglong ? 12 | ULONGLONG = BYTE * 8 13 | 14 | class IO_COUNTERS(Structure): 15 | # The IO_COUNTERS struct is 6 ULONGLONGs. 16 | # TODO: Replace with non-dummy fields. 17 | _fields_ = [('dummy', ULONGLONG * 6)] 18 | 19 | class JOBOBJECT_BASIC_ACCOUNTING_INFORMATION(Structure): 20 | _fields_ = [('TotalUserTime', LARGE_INTEGER), 21 | ('TotalKernelTime', LARGE_INTEGER), 22 | ('ThisPeriodTotalUserTime', LARGE_INTEGER), 23 | ('ThisPeriodTotalKernelTime', LARGE_INTEGER), 24 | ('TotalPageFaultCount', DWORD), 25 | ('TotalProcesses', DWORD), 26 | ('ActiveProcesses', DWORD), 27 | ('TotalTerminatedProcesses', DWORD)] 28 | 29 | class JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION(Structure): 30 | _fields_ = [('BasicInfo', JOBOBJECT_BASIC_ACCOUNTING_INFORMATION), 31 | ('IoInfo', IO_COUNTERS)] 32 | 33 | # see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx 34 | class JOBOBJECT_BASIC_LIMIT_INFORMATION(Structure): 35 | _fields_ = [('PerProcessUserTimeLimit', LARGE_INTEGER), 36 | ('PerJobUserTimeLimit', LARGE_INTEGER), 37 | ('LimitFlags', DWORD), 38 | ('MinimumWorkingSetSize', SIZE_T), 39 | ('MaximumWorkingSetSize', SIZE_T), 40 | ('ActiveProcessLimit', DWORD), 41 | ('Affinity', ULONG_PTR), 42 | ('PriorityClass', DWORD), 43 | ('SchedulingClass', DWORD) 44 | ] 45 | 46 | # see http://msdn.microsoft.com/en-us/library/ms684156%28VS.85%29.aspx 47 | class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(Structure): 48 | _fields_ = [('BasicLimitInformation', JOBOBJECT_BASIC_LIMIT_INFORMATION), 49 | ('IoInfo', IO_COUNTERS), 50 | ('ProcessMemoryLimit', SIZE_T), 51 | ('JobMemoryLimit', SIZE_T), 52 | ('PeakProcessMemoryUsed', SIZE_T), 53 | ('PeakJobMemoryUsed', SIZE_T)] 54 | 55 | # XXX Magical numbers like 8 should be documented 56 | JobObjectBasicAndIoAccountingInformation = 8 57 | 58 | # ...like magical number 9 comes from 59 | # http://community.flexerasoftware.com/archive/index.php?t-181670.html 60 | # I wish I had a more canonical source 61 | JobObjectExtendedLimitInformation = 9 62 | 63 | class JobObjectInfo(object): 64 | mapping = { 'JobObjectBasicAndIoAccountingInformation': 8, 65 | 'JobObjectExtendedLimitInformation': 9 66 | } 67 | structures = { 8: JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION, 68 | 9: JOBOBJECT_EXTENDED_LIMIT_INFORMATION 69 | } 70 | def __init__(self, _class): 71 | if isinstance(_class, str): 72 | assert _class in self.mapping, 'Class should be one of %s; you gave %s' % (self.mapping, _class) 73 | _class = self.mapping[_class] 74 | assert _class in self.structures, 'Class should be one of %s; you gave %s' % (self.structures, _class) 75 | self.code = _class 76 | self.info = self.structures[_class]() 77 | 78 | 79 | QueryInformationJobObjectProto = WINFUNCTYPE( 80 | BOOL, # Return type 81 | HANDLE, # hJob 82 | DWORD, # JobObjectInfoClass 83 | LPVOID, # lpJobObjectInfo 84 | DWORD, # cbJobObjectInfoLength 85 | LPDWORD # lpReturnLength 86 | ) 87 | 88 | QueryInformationJobObjectFlags = ( 89 | (1, 'hJob'), 90 | (1, 'JobObjectInfoClass'), 91 | (1, 'lpJobObjectInfo'), 92 | (1, 'cbJobObjectInfoLength'), 93 | (1, 'lpReturnLength', None) 94 | ) 95 | 96 | _QueryInformationJobObject = QueryInformationJobObjectProto( 97 | ('QueryInformationJobObject', windll.kernel32), 98 | QueryInformationJobObjectFlags 99 | ) 100 | 101 | class SubscriptableReadOnlyStruct(object): 102 | def __init__(self, struct): 103 | self._struct = struct 104 | 105 | def _delegate(self, name): 106 | result = getattr(self._struct, name) 107 | if isinstance(result, Structure): 108 | return SubscriptableReadOnlyStruct(result) 109 | return result 110 | 111 | def __getitem__(self, name): 112 | match = [fname for fname, ftype in self._struct._fields_ 113 | if fname == name] 114 | if match: 115 | return self._delegate(name) 116 | raise KeyError(name) 117 | 118 | def __getattr__(self, name): 119 | return self._delegate(name) 120 | 121 | def QueryInformationJobObject(hJob, JobObjectInfoClass): 122 | jobinfo = JobObjectInfo(JobObjectInfoClass) 123 | result = _QueryInformationJobObject( 124 | hJob=hJob, 125 | JobObjectInfoClass=jobinfo.code, 126 | lpJobObjectInfo=addressof(jobinfo.info), 127 | cbJobObjectInfoLength=sizeof(jobinfo.info) 128 | ) 129 | if not result: 130 | raise WinError() 131 | return SubscriptableReadOnlyStruct(jobinfo.info) 132 | 133 | def test_qijo(): 134 | from .killableprocess import Popen 135 | 136 | popen = Popen('c:\\windows\\notepad.exe') 137 | 138 | try: 139 | result = QueryInformationJobObject(0, 8) 140 | raise AssertionError('throw should occur') 141 | except WindowsError as e: 142 | pass 143 | 144 | try: 145 | result = QueryInformationJobObject(0, 1) 146 | raise AssertionError('throw should occur') 147 | except NotImplementedError as e: 148 | pass 149 | 150 | result = QueryInformationJobObject(popen._job, 8) 151 | if result['BasicInfo']['ActiveProcesses'] != 1: 152 | raise AssertionError('expected ActiveProcesses to be 1') 153 | popen.kill() 154 | 155 | result = QueryInformationJobObject(popen._job, 8) 156 | if result.BasicInfo.ActiveProcesses != 0: 157 | raise AssertionError('expected ActiveProcesses to be 0') 158 | -------------------------------------------------------------------------------- /repls/sublimeutop_repl.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | from __future__ import absolute_import, print_function, division 3 | 4 | try: 5 | from queue import Queue 6 | except ImportError: 7 | from Queue import Queue 8 | from .subprocess_repl import SubprocessRepl 9 | 10 | class SublimeUTopRepl(SubprocessRepl): 11 | TYPE = "sublime_utop" 12 | 13 | def __init__(self, encoding, **kwds): 14 | super(SublimeUTopRepl, self).__init__(encoding, apiv2=True, **kwds) 15 | 16 | # Buffer for reassembling stanzas arrived from utop. 17 | self._buffer = b'' 18 | 19 | # Phrase pending input with mapping of utop-lines to 20 | # SublimeREPL-view-lines. 21 | self._phrase = [] 22 | self._phrase_line_begins = [] 23 | 24 | # Completion state. 25 | self._completions = None 26 | self._completion_prefix = "" 27 | self._completion_queue = Queue() 28 | 29 | def autocomplete_available(self): 30 | return True 31 | 32 | def autocomplete_completions(self, whole_line, pos_in_line, 33 | prefix, whole_prefix, locations): 34 | self._completion_prefix = prefix 35 | self.write_command('complete', '', [whole_prefix]) 36 | 37 | # This would block the UI. When REPL works correctly, 38 | # this blocks for less than 100ms. 39 | return [(x, x) for x in self._completion_queue.get(timeout=500)] 40 | 41 | # 42 | # USER INTERACTION LEVEL 43 | # 44 | # User interaction consists of visible artifacts (prompt, etc) 45 | # and input in form of complete expressions. History is handled 46 | # by SublimeREPL. 47 | # 48 | 49 | def compose_highlights(self, a, b): 50 | highlights = [] 51 | 52 | # Highlight each fragment of line which lies in [a;b). 53 | for (line, loc) in zip(self._phrase, self._phrase_line_begins): 54 | # Does this line have any highlight? 55 | if a < len(line): 56 | # Yeah, does it end here? 57 | if b <= len(line): 58 | # Highlight the requested area and return. 59 | highlights.append((loc + a, loc + b)) 60 | break 61 | else: 62 | # Highlight till the end of line. 63 | highlights.append((loc + a, loc + len(line))) 64 | 65 | # Shift the highlight region left by len(line) and 66 | # continue. 67 | a -= len(line) + 1 68 | b -= len(line) + 1 69 | # Always start from beginning of line for next lines. 70 | if a < 0: 71 | a = 0 72 | 73 | return [('highlight', x) for x in highlights] 74 | 75 | def read(self): 76 | stanza = self.read_stanza() 77 | if stanza is None: 78 | return None 79 | 80 | key, value = stanza 81 | if key == 'accept': 82 | packet = [] 83 | 84 | if value != "": 85 | a, b = map(int, value.split(',')) 86 | packet.extend(self.compose_highlights(a, b)) 87 | 88 | # We've finished this phrase. 89 | self._phrase = [] 90 | self._phrase_line_begins = [] 91 | 92 | # Erase prompt. Accept is the first stanza we receive in 93 | # reply to input; immediately after it may follow stdout/stderr 94 | # and prompt stanzas in any order. To avoid garbled text, 95 | # we need to erase prompt before continuing. 96 | packet.append(('prompt', '')) 97 | packet.append(('output', '\n')) 98 | return packet 99 | 100 | elif key == 'stdout': 101 | return [('output', value + '\n')] 102 | elif key == 'stderr': 103 | return [('output', '! ' + value + '\n')] 104 | 105 | elif key == 'prompt': 106 | return [('prompt', '# ')] 107 | elif key == 'continue': 108 | return [('prompt', '\n ')] 109 | 110 | # Full completion reply is completion-start..completion*..completion-end. 111 | # Names are fully qualified, i.e. Thread. 112 | elif key == 'completion-start': 113 | self._completions = [] 114 | return [] 115 | elif key == 'completion': 116 | self._completions.append(value) 117 | return [] 118 | elif key == 'completion-stop': 119 | self._completion_queue.put(self._completions) 120 | self._completions = None 121 | return [] 122 | 123 | # Word completion reply is just completion-word stanza. 124 | # Names are partial, i.e. ead ([Thr]ead). 125 | elif key == 'completion-word': 126 | self._completion_queue.put([self._completion_prefix + value]) 127 | return [] 128 | 129 | # Stuff we don't care about: phrase-terminator. 130 | # Stuff we never receive: history-*. 131 | else: 132 | return [] 133 | 134 | def write(self, expression, location=None): 135 | # If the phrase is incomplete, utop will not remember it, so 136 | # we need to account for it here. Also, Shift+Enter will add a literal 137 | # newline, which would otherwise break protocol. 138 | for line in expression.split('\n'): 139 | self._phrase.append(line) 140 | if location is not None: 141 | self._phrase_line_begins.append(location) 142 | location += len(line) + 1 143 | 144 | self.write_command('input', 'allow-incomplete', self._phrase) 145 | 146 | # 147 | # COMMAND LEVEL 148 | # 149 | # A command is a collection of stanzas: one begin stanza, 150 | # zero or more data stanzas, and one end stanza. 151 | # 152 | 153 | def write_command(self, command, options, data): 154 | self.write_stanza(command, options) 155 | for datum in data: 156 | self.write_stanza('data', datum) 157 | self.write_stanza('end') 158 | 159 | # 160 | # STANZA LEVEL 161 | # 162 | # A stanza is a statement of form "key:value\n". 163 | # Decoding and encoding is done on the stanza level. 164 | # 165 | 166 | def read_stanza(self): 167 | while True: 168 | try: 169 | stanza_end = self._buffer.index(b'\n') 170 | stanza = self.decoder.decode(self._buffer[:stanza_end]) 171 | self._buffer = self._buffer[stanza_end+1:] 172 | 173 | colon = stanza.index(':') 174 | return stanza[:colon], stanza[colon+1:] 175 | except ValueError: 176 | bytes = self.read_bytes() 177 | if not bytes: 178 | return None 179 | else: 180 | self._buffer += bytes 181 | 182 | def write_stanza(self, key, value=''): 183 | (bytes, _) = self.encoder(key + ':' + value + '\n') 184 | self.write_bytes(bytes) 185 | -------------------------------------------------------------------------------- /config/Io/Io.tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keyEquivalent 6 | ^~I 7 | name 8 | Io Repl 9 | patterns 10 | 11 | 12 | captures 13 | 14 | 1 15 | 16 | name 17 | meta.empty-parenthesis.io 18 | 19 | 20 | comment 21 | we match this to overload return inside () --Allan; scoping rules for what gets the scope have changed, so we now group the ) instead of the ( -- Rob 22 | match 23 | \((\)) 24 | 25 | 26 | captures 27 | 28 | 1 29 | 30 | name 31 | meta.comma-parenthesis.io 32 | 33 | 34 | comment 35 | We want to do the same for ,) -- Seckar; same as above -- Rob 36 | match 37 | \,(\)) 38 | 39 | 40 | match 41 | \b(if|ifTrue|ifFalse|ifTrueIfFalse|for|loop|reverseForeach|foreach|map|continue|break|while|do|return)\b 42 | name 43 | keyword.control.io 44 | 45 | 46 | begin 47 | /\* 48 | captures 49 | 50 | 0 51 | 52 | name 53 | punctuation.definition.comment.io 54 | 55 | 56 | end 57 | \*/ 58 | name 59 | comment.block.io 60 | 61 | 62 | begin 63 | (^[ \t]+)?(?=//) 64 | beginCaptures 65 | 66 | 1 67 | 68 | name 69 | punctuation.whitespace.comment.leading.io 70 | 71 | 72 | end 73 | (?!\G) 74 | patterns 75 | 76 | 77 | begin 78 | // 79 | beginCaptures 80 | 81 | 0 82 | 83 | name 84 | punctuation.definition.comment.io 85 | 86 | 87 | end 88 | \n 89 | name 90 | comment.line.double-slash.io 91 | 92 | 93 | 94 | 95 | begin 96 | (^[ \t]+)?(?=#) 97 | beginCaptures 98 | 99 | 1 100 | 101 | name 102 | punctuation.whitespace.comment.leading.io 103 | 104 | 105 | end 106 | (?!\G) 107 | patterns 108 | 109 | 110 | begin 111 | # 112 | beginCaptures 113 | 114 | 0 115 | 116 | name 117 | punctuation.definition.comment.io 118 | 119 | 120 | end 121 | \n 122 | name 123 | comment.line.number-sign.io 124 | 125 | 126 | 127 | 128 | comment 129 | I wonder if some of this isn't variable.other.language? --Allan; scoping this as variable.language to match Objective-C's handling of 'self', which is inconsistent with C++'s handling of 'this' but perhaps intentionally so -- Rob 130 | match 131 | \b(self|sender|target|proto|protos|parent)\b 132 | name 133 | variable.language.io 134 | 135 | 136 | match 137 | <=|>=|=|:=|\*|\||\|\||\+|-|/|&|&&|>|<|\?|@|@@|\b(and|or)\b 138 | name 139 | keyword.operator.io 140 | 141 | 142 | match 143 | \bGL[\w_]+\b 144 | name 145 | constant.other.io 146 | 147 | 148 | match 149 | \b([A-Z](\w+)?)\b 150 | name 151 | support.class.io 152 | 153 | 154 | match 155 | \b(clone|call|init|method|list|vector|block|(\w+(?=\s*\()))\b 156 | name 157 | support.function.io 158 | 159 | 160 | match 161 | \b(gl(u|ut)?[A-Z]\w+)\b 162 | name 163 | support.function.open-gl.io 164 | 165 | 166 | begin 167 | """ 168 | beginCaptures 169 | 170 | 0 171 | 172 | name 173 | punctuation.definition.string.begin.io 174 | 175 | 176 | end 177 | """ 178 | endCaptures 179 | 180 | 0 181 | 182 | name 183 | punctuation.definition.string.end.io 184 | 185 | 186 | name 187 | string.quoted.triple.io 188 | patterns 189 | 190 | 191 | match 192 | \\. 193 | name 194 | constant.character.escape.io 195 | 196 | 197 | 198 | 199 | begin 200 | " 201 | beginCaptures 202 | 203 | 0 204 | 205 | name 206 | punctuation.definition.string.begin.io 207 | 208 | 209 | end 210 | " 211 | endCaptures 212 | 213 | 0 214 | 215 | name 216 | punctuation.definition.string.end.io 217 | 218 | 219 | name 220 | string.quoted.double.io 221 | patterns 222 | 223 | 224 | match 225 | \\. 226 | name 227 | constant.character.escape.io 228 | 229 | 230 | 231 | 232 | match 233 | \b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?\b 234 | name 235 | constant.numeric.io 236 | 237 | 238 | match 239 | (Lobby)\b 240 | name 241 | variable.other.global.io 242 | 243 | 244 | match 245 | \b(TRUE|true|FALSE|false|NULL|null|Null|Nil|nil|YES|NO)\b 246 | name 247 | constant.language.io 248 | 249 | 250 | scopeName 251 | source.io 252 | uuid 253 | 52E416F3-9DF2-4579-8BC6-C54EBEF94423 254 | 255 | 256 | -------------------------------------------------------------------------------- /lang_integration.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals, print_function, division 2 | import sublime 3 | import sublime_plugin 4 | 5 | import re 6 | import os 7 | import glob 8 | import os.path 9 | import socket 10 | from functools import partial 11 | from contextlib import closing 12 | 13 | SETTINGS_FILE = "SublimeREPL.sublime-settings" 14 | 15 | class ClojureAutoTelnetRepl(sublime_plugin.WindowCommand): 16 | def is_running(self, port_str): 17 | """Check if port is open on localhost""" 18 | port = int(port_str) 19 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 20 | res = s.connect_ex(("127.0.0.1", port)) 21 | s.close() 22 | return res == 0 23 | 24 | def choices(self): 25 | choices = [] 26 | for folder in self.window.folders(): 27 | proj_file = os.path.join(folder, "project.clj") 28 | try: 29 | with open(proj_file) as f: 30 | data = f.read() 31 | port_match = re.search(":repl-port\s+(\d{1,})", data) 32 | if not port_match: 33 | continue 34 | port = port_match.group(1) 35 | description = proj_file 36 | desc_match = re.search(r':description\s+"([^"]+)"', data) 37 | if desc_match: 38 | description = desc_match.group(1) 39 | if self.is_running(port): 40 | description += " (active)" 41 | else: 42 | description += " (not responding)" 43 | choices.append([description, port]) 44 | except IOError as e: 45 | pass # just ignore it, no file or no access 46 | 47 | return choices + [["Custom telnet", "Pick your own telnet port number to Lein REPL"]] 48 | 49 | def run(self): 50 | choices = self.choices() 51 | if len(choices) == 1: #only custom telnet action 52 | self.on_done(choices, 0) 53 | else: 54 | on_done = partial(self.on_done, choices) 55 | self.window.show_quick_panel(self.choices(), on_done) 56 | 57 | def on_done(self, choices, index): 58 | if index == -1: 59 | return 60 | if index == len(choices) - 1: 61 | self.window.show_input_panel("Enter port number", "", 62 | self.open_telnet_repl, 63 | None, None) 64 | return 65 | self.open_telnet_repl(choices[index][1]) 66 | 67 | def open_telnet_repl(self, port_str): 68 | try: 69 | port = int(port_str) 70 | except ValueError: 71 | return 72 | self.window.run_command("repl_open", {"type":"telnet", "encoding":"utf8", "host":"localhost", "port":port, 73 | "external_id":"clojure", "syntax":"Packages/Clojure/Clojure.tmLanguage"}) 74 | 75 | 76 | def scan_for_virtualenvs(venv_paths): 77 | bin_dir = "Scripts" if os.name == "nt" else "bin" 78 | found_dirs = set() 79 | for venv_path in venv_paths: 80 | p = os.path.expanduser(venv_path) 81 | pattern = os.path.join(p, "*", bin_dir, "activate_this.py") 82 | found_dirs.update(list(map(os.path.dirname, glob.glob(pattern)))) 83 | return sorted(found_dirs) 84 | 85 | 86 | class PythonVirtualenvRepl(sublime_plugin.WindowCommand): 87 | def _scan(self): 88 | venv_paths = sublime.load_settings(SETTINGS_FILE).get("python_virtualenv_paths", []) 89 | return scan_for_virtualenvs(venv_paths) 90 | 91 | def run_virtualenv(self, choices, index): 92 | if index == -1: 93 | return 94 | (name, directory) = choices[index] 95 | activate_file = os.path.join(directory, "activate_this.py") 96 | python_executable = os.path.join(directory, "python") 97 | path_separator = ":" 98 | if os.name == "nt": 99 | python_executable += ".exe" # ;-) 100 | path_separator = ";" 101 | 102 | self.window.run_command("repl_open", 103 | { 104 | "encoding":"utf8", 105 | "type": "subprocess", 106 | "autocomplete_server": True, 107 | "extend_env": { 108 | "PATH": directory + path_separator + "{PATH}", 109 | "SUBLIMEREPL_ACTIVATE_THIS": activate_file, 110 | "PYTHONIOENCODING": "utf-8" 111 | }, 112 | "cmd": [python_executable, "-u", "${packages}/SublimeREPL/config/Python/ipy_repl.py"], 113 | "cwd": "$file_path", 114 | "encoding": "utf8", 115 | "syntax": "Packages/Python/Python.tmLanguage", 116 | "external_id": "python" 117 | }) 118 | 119 | def run(self): 120 | choices = self._scan() 121 | nice_choices = [[path.split(os.path.sep)[-2], path] for path in choices] 122 | self.window.show_quick_panel(nice_choices, partial(self.run_virtualenv, nice_choices)) 123 | 124 | 125 | VENV_SCAN_CODE = """ 126 | import os 127 | import glob 128 | import os.path 129 | 130 | venv_paths = channel.receive() 131 | bin_dir = "Scripts" if os.name == "nt" else "bin" 132 | found_dirs = set() 133 | for venv_path in venv_paths: 134 | p = os.path.expanduser(venv_path) 135 | pattern = os.path.join(p, "*", bin_dir, "activate_this.py") 136 | found_dirs.update(map(os.path.dirname, glob.glob(pattern))) 137 | 138 | channel.send(found_dirs) 139 | channel.close() 140 | 141 | """ 142 | 143 | class ExecnetVirtualenvRepl(sublime_plugin.WindowCommand): 144 | def run(self): 145 | self.window.show_input_panel("SSH connection (eg. user@host)", "", self.on_ssh_select, None, None) 146 | 147 | def on_ssh_select(self, host_string): 148 | import execnet 149 | venv_paths = sublime.load_settings(SETTINGS_FILE).get("python_virtualenv_paths", []) 150 | try: 151 | gw = execnet.makegateway("ssh=" + host_string) 152 | ch = gw.remote_exec(VENV_SCAN_CODE) 153 | except Exception as e: 154 | sublime.error_message(repr(e)) 155 | return 156 | 157 | with closing(ch): 158 | ch.send(venv_paths) 159 | directories = ch.receive(60) 160 | gw.exit() 161 | 162 | choices = [[host_string + ":" + path.split(os.path.sep)[-2], path] for path in sorted(directories)] 163 | nice_choices = [["w/o venv", "n/a"]] + choices 164 | self.window.show_quick_panel(nice_choices, partial(self.run_virtualenv, host_string, nice_choices)) 165 | 166 | def run_virtualenv(self, host_string, nice_choices, index): 167 | if index == -1: 168 | return 169 | if index == 0: 170 | connection_string = "ssh={host}".format(host=host_string) 171 | ps1 = "({host}@) >>> ".format(host=host_string) 172 | activate_file = "" 173 | else: 174 | (name, directory) = nice_choices[index] 175 | activate_file = os.path.join(directory, "activate_this.py") 176 | python_file = os.path.join(directory, "python") 177 | ps1 = "({name}) >>> ".format(name=name, host=host_string) 178 | connection_string = "ssh={host}//env:PATH={dir}//python={python}".format( 179 | host=host_string, 180 | dir=directory, 181 | python=python_file 182 | ) 183 | 184 | self.window.run_command("repl_open", 185 | { 186 | "type": "execnet_repl", 187 | "encoding": "utf8", 188 | "syntax": "Packages/Python/Python.tmLanguage", 189 | "connection_string": connection_string, 190 | "activate_file": activate_file, 191 | "ps1": ps1 192 | }) 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # SublimeREPL documentation build configuration file, created by 4 | # sphinx-quickstart on Sun Feb 26 16:38:41 2012. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # If your documentation needs a minimal Sphinx version, state it here. 24 | #needs_sphinx = '1.0' 25 | 26 | # Add any Sphinx extension module names here, as strings. They can be extensions 27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 28 | extensions = [] 29 | 30 | # Add any paths that contain templates here, relative to this directory. 31 | templates_path = ['_templates'] 32 | 33 | # The suffix of source filenames. 34 | source_suffix = '.rst' 35 | 36 | # The encoding of source files. 37 | #source_encoding = 'utf-8-sig' 38 | 39 | # The master toctree document. 40 | master_doc = 'index' 41 | 42 | # General information about the project. 43 | project = 'SublimeREPL' 44 | copyright = '2012, Wojciech Bederski' 45 | 46 | # The version info for the project you're documenting, acts as replacement for 47 | # |version| and |release|, also used in various other places throughout the 48 | # built documents. 49 | # 50 | # The short X.Y version. 51 | version = '1.0' 52 | # The full version, including alpha/beta/rc tags. 53 | release = '1.0.30' 54 | 55 | # The language for content autogenerated by Sphinx. Refer to documentation 56 | # for a list of supported languages. 57 | #language = None 58 | 59 | # There are two options for replacing |today|: either, you set today to some 60 | # non-false value, then it is used: 61 | #today = '' 62 | # Else, today_fmt is used as the format for a strftime call. 63 | #today_fmt = '%B %d, %Y' 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | exclude_patterns = ['_build'] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. See the documentation for 93 | # a list of builtin themes. 94 | html_theme = 'default' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | #html_theme_options = {} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | #html_title = None 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | #html_sidebars = {} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | #html_domain_indices = True 142 | 143 | # If false, no index is generated. 144 | #html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | #html_show_sourcelink = True 151 | 152 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 153 | #html_show_sphinx = True 154 | 155 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 156 | #html_show_copyright = True 157 | 158 | # If true, an OpenSearch description file will be output, and all pages will 159 | # contain a tag referring to it. The value of this option must be the 160 | # base URL from which the finished HTML is served. 161 | #html_use_opensearch = '' 162 | 163 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 164 | #html_file_suffix = None 165 | 166 | # Output file base name for HTML help builder. 167 | htmlhelp_basename = 'SublimeREPLdoc' 168 | 169 | 170 | # -- Options for LaTeX output -------------------------------------------------- 171 | 172 | latex_elements = { 173 | # The paper size ('letterpaper' or 'a4paper'). 174 | #'papersize': 'letterpaper', 175 | 176 | # The font size ('10pt', '11pt' or '12pt'). 177 | #'pointsize': '10pt', 178 | 179 | # Additional stuff for the LaTeX preamble. 180 | #'preamble': '', 181 | } 182 | 183 | # Grouping the document tree into LaTeX files. List of tuples 184 | # (source start file, target name, title, author, documentclass [howto/manual]). 185 | latex_documents = [ 186 | ('index', 'SublimeREPL.tex', 'SublimeREPL Documentation', 187 | 'Wojciech Bederski', 'manual'), 188 | ] 189 | 190 | # The name of an image file (relative to this directory) to place at the top of 191 | # the title page. 192 | #latex_logo = None 193 | 194 | # For "manual" documents, if this is true, then toplevel headings are parts, 195 | # not chapters. 196 | #latex_use_parts = False 197 | 198 | # If true, show page references after internal links. 199 | #latex_show_pagerefs = False 200 | 201 | # If true, show URL addresses after external links. 202 | #latex_show_urls = False 203 | 204 | # Documents to append as an appendix to all manuals. 205 | #latex_appendices = [] 206 | 207 | # If false, no module index is generated. 208 | #latex_domain_indices = True 209 | 210 | 211 | # -- Options for manual page output -------------------------------------------- 212 | 213 | # One entry per manual page. List of tuples 214 | # (source start file, name, description, authors, manual section). 215 | man_pages = [ 216 | ('index', 'sublimerepl', 'SublimeREPL Documentation', 217 | ['Wojciech Bederski'], 1) 218 | ] 219 | 220 | # If true, show URL addresses after external links. 221 | #man_show_urls = False 222 | 223 | 224 | # -- Options for Texinfo output ------------------------------------------------ 225 | 226 | # Grouping the document tree into Texinfo files. List of tuples 227 | # (source start file, target name, title, author, 228 | # dir menu entry, description, category) 229 | texinfo_documents = [ 230 | ('index', 'SublimeREPL', 'SublimeREPL Documentation', 231 | 'Wojciech Bederski', 'SublimeREPL', 'One line description of project.', 232 | 'Miscellaneous'), 233 | ] 234 | 235 | # Documents to append as an appendix to all manuals. 236 | #texinfo_appendices = [] 237 | 238 | # If false, no module index is generated. 239 | #texinfo_domain_indices = True 240 | 241 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 242 | #texinfo_show_urls = 'footnote' 243 | -------------------------------------------------------------------------------- /text_transfer.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals, print_function, division 2 | 3 | import re 4 | import sublime_plugin 5 | import sublime 6 | from collections import defaultdict 7 | import tempfile 8 | import binascii 9 | 10 | try: 11 | from .sublimerepl import manager, SETTINGS_FILE 12 | except (ImportError, ValueError): 13 | from sublimerepl import manager, SETTINGS_FILE 14 | 15 | 16 | def default_sender(repl, text, view=None, repl_view=None): 17 | if repl.apiv2: 18 | repl.write(text, location=repl_view.view.size() - len(text)) 19 | else: 20 | repl.write(text) 21 | 22 | if view is None or not sublime.load_settings(SETTINGS_FILE).get('focus_view_on_transfer'): 23 | return 24 | active_window = sublime.active_window() 25 | active_view = active_window.active_view() 26 | target_view = repl_view.view 27 | if target_view == active_view: 28 | return # 29 | active_group = sublime.active_window().active_group() 30 | if target_view in active_window.views_in_group(active_group): 31 | return # same group, dont switch 32 | active_window.focus_view(target_view) 33 | active_window.focus_view(view) 34 | 35 | 36 | """Senders is a dict of functions used to transfer text to repl as a repl 37 | specific load_file action""" 38 | SENDERS = defaultdict(lambda: default_sender) 39 | 40 | 41 | def sender(external_id,): 42 | def wrap(func): 43 | SENDERS[external_id] = func 44 | return wrap 45 | 46 | 47 | @sender("coffee") 48 | def coffee(repl, text, view=None, repl_view=None): 49 | """ 50 | use CoffeeScript multiline hack 51 | http://coffeescript.org/documentation/docs/repl.html 52 | """ 53 | default_sender(repl, text.replace("\n", u'\uFF00') + "\n", view, repl_view) 54 | 55 | @sender("python") 56 | def python_sender(repl, text, view=None, repl_view=None): 57 | text_wo_encoding = re.sub( 58 | pattern=r"#.*coding[:=]\s*([-\w.]+)", 59 | repl="# ", 60 | string=text, 61 | count=1) 62 | code = binascii.hexlify(text_wo_encoding.encode("utf-8")) 63 | execute = ''.join([ 64 | 'from binascii import unhexlify as __un; exec(compile(__un("', 65 | str(code.decode('ascii')), 66 | '").decode("utf-8"), "", "exec"))\n' 67 | ]) 68 | return default_sender(repl, execute, view, repl_view) 69 | 70 | 71 | @sender("ruby") 72 | def ruby_sender(repl, text, view=None, repl_view=None): 73 | code = binascii.b2a_base64(text.encode("utf-8")) 74 | payload = "begin require 'base64'; eval(Base64.decode64('%s'), binding=TOPLEVEL_BINDING) end\n" % (code.decode("ascii"),) 75 | return default_sender(repl, payload, view, repl_view) 76 | 77 | 78 | # custom clojure sender that makes sure that all selections are 79 | # evaluated in the namespace declared by the file they are in 80 | @sender("clojure") 81 | def clojure_sender(repl, text, view, repl_view=None): 82 | # call (load-string) instead of just writing the string so 83 | # that syntax errors are caught and thrown back immediately. 84 | # also, escape backslashes and double-quotes 85 | text = '(load-string "' + text.strip().replace('\\', r'\\').replace('"', r'\"') + '")' 86 | 87 | # find the first non-commented statement from the start of the file 88 | namespacedecl = view.find(r"^[^;]*?\(", 0) 89 | 90 | # if it's a namespace declaration, go search for the namespace name 91 | if namespacedecl and view.scope_name(namespacedecl.end()-1).startswith("source.clojure meta.function.namespace.clojure"): 92 | namespacedecl = view.extract_scope(namespacedecl.end()-1) 93 | 94 | # we're looking for the first symbol within the declaration that 95 | # looks like a namespace and isn't metadata, a comment, etc. 96 | pos = namespacedecl.begin() + 3 97 | while pos < namespacedecl.end(): 98 | # see http://clojure.org/reader for a description of valid 99 | # namespace names. the inital } or whitespace make sure we're 100 | # not matching on keywords etc. 101 | namespace = view.find(r"[\}\s][A-Za-z\_!\?\*\+\-][\w!\?\*\+\-:]*(\.[\w!\?\*\+\-:]+)*", pos) 102 | 103 | if not namespace: 104 | # couldn't find the namespace name within the declaration. suspicious. 105 | break 106 | elif view.scope_name(namespace.begin() + 1).startswith("source.clojure meta.function.namespace.clojure entity.name.namespace.clojure"): 107 | # looks alright, we've got our namespace! 108 | # switch to namespace before executing command 109 | 110 | # we could do this explicitly by calling (ns), (in-ns) etc: 111 | # text = "(ns " + view.substr(namespace)[1:] + ") " + text 112 | # but this would not only result in an extra return value 113 | # printed to the user, the repl would also remain in that 114 | # namespace after execution, so instead we do the same thing 115 | # that swank-clojure does: 116 | text = "(binding [*ns* (or (find-ns '" + view.substr(namespace)[1:] + ") (find-ns 'user))] " + text + ')' 117 | # i.e. we temporarily switch to the namespace if it has already 118 | # been created, otherwise we execute it in 'user. the most 119 | # elegant option for this would probably be: 120 | # text = "(binding [*ns* (create-ns '" + view.substr(namespace)[1:] + ")] " + text + ')' 121 | # but this can lead to problems because of newly created 122 | # namespaces not automatically referring to clojure.core 123 | # (see https://groups.google.com/forum/?fromgroups=#!topic/clojure/Th-Bqq68hfo) 124 | break 125 | else: 126 | # false alarm (metadata or a comment), keep looking 127 | pos = namespace.end() 128 | return default_sender(repl, text + repl.cmd_postfix, view, repl_view) 129 | 130 | class ReplViewWrite(sublime_plugin.TextCommand): 131 | def run(self, edit, external_id, text): 132 | for rv in manager.find_repl(external_id): 133 | rv.append_input_text(text) 134 | break # send to first repl found 135 | else: 136 | sublime.error_message("Cannot find REPL for '{0}'".format(external_id)) 137 | 138 | 139 | class ReplSend(sublime_plugin.TextCommand): 140 | def run(self, edit, external_id, text, with_auto_postfix=True): 141 | for rv in manager.find_repl(external_id): 142 | if with_auto_postfix: 143 | text += rv.repl.cmd_postfix 144 | if sublime.load_settings(SETTINGS_FILE).get('show_transferred_text'): 145 | rv.append_input_text(text) 146 | rv.adjust_end() 147 | SENDERS[external_id](rv.repl, text, self.view, rv) 148 | break 149 | else: 150 | sublime.error_message("Cannot find REPL for '{}'".format(external_id)) 151 | 152 | 153 | class ReplTransferCurrent(sublime_plugin.TextCommand): 154 | def run(self, edit, scope="selection", action="send"): 155 | text = "" 156 | if scope == "selection": 157 | text = self.selected_text() 158 | elif scope == "lines": 159 | text = self.selected_lines() 160 | elif scope == "function": 161 | text = self.selected_functions() 162 | elif scope == "block": 163 | text = self.selected_blocks() 164 | elif scope == "file": 165 | text = self.selected_file() 166 | cmd = "repl_" + action 167 | self.view.window().run_command(cmd, {"external_id": self.repl_external_id(), "text": text}) 168 | 169 | def repl_external_id(self): 170 | return self.view.scope_name(0).split(" ")[0].split(".", 1)[1] 171 | 172 | def selected_text(self): 173 | v = self.view 174 | parts = [v.substr(region) for region in v.sel()] 175 | return "".join(parts) 176 | 177 | def selected_blocks(self): 178 | # TODO: Clojure only for now 179 | v = self.view 180 | strs = [] 181 | old_sel = list(v.sel()) 182 | v.run_command("expand_selection", {"to": "brackets"}) 183 | v.run_command("expand_selection", {"to": "brackets"}) 184 | for s in v.sel(): 185 | strs.append(v.substr(s)) 186 | v.sel().clear() 187 | for s in old_sel: 188 | v.sel().add(s) 189 | return "\n\n".join(strs) 190 | 191 | def selected_lines(self): 192 | v = self.view 193 | parts = [] 194 | for sel in v.sel(): 195 | for line in v.lines(sel): 196 | parts.append(v.substr(line)) 197 | return "\n".join(parts) 198 | 199 | def selected_file(self): 200 | v = self.view 201 | return v.substr(sublime.Region(0, v.size())) 202 | -------------------------------------------------------------------------------- /repls/subprocess_repl.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2011, Wojciech Bederski (wuub.net) 3 | # All rights reserved. 4 | # See LICENSE.txt for details. 5 | from __future__ import absolute_import, unicode_literals, print_function, division 6 | 7 | import subprocess 8 | import os 9 | import sys 10 | from .repl import Repl 11 | import signal 12 | from sublime import load_settings, error_message 13 | from .autocomplete_server import AutocompleteServer 14 | from .killableprocess import Popen 15 | 16 | PY3 = sys.version_info[0] == 3 17 | 18 | if os.name == 'posix': 19 | POSIX = True 20 | import fcntl 21 | import select 22 | else: 23 | POSIX = False 24 | 25 | 26 | class Unsupported(Exception): 27 | def __init__(self, msgs): 28 | super(Unsupported, self).__init__() 29 | self.msgs = msgs 30 | 31 | def __repr__(self): 32 | return "\n".join(self.msgs) 33 | 34 | 35 | def win_find_executable(executable, env): 36 | """Explicetely looks for executable in env["PATH"]""" 37 | if os.path.dirname(executable): 38 | return executable # executable is already absolute filepath 39 | path = env.get("PATH", "") 40 | pathext = env.get("PATHEXT") or ".EXE" 41 | dirs = path.split(os.path.pathsep) 42 | (base, ext) = os.path.splitext(executable) 43 | if ext: 44 | extensions = [ext] 45 | else: 46 | extensions = pathext.split(os.path.pathsep) 47 | for directory in dirs: 48 | for extension in extensions: 49 | filepath = os.path.join(directory, base + extension) 50 | if os.path.exists(filepath): 51 | return filepath 52 | return None 53 | 54 | 55 | class SubprocessRepl(Repl): 56 | TYPE = "subprocess" 57 | 58 | def __init__(self, encoding, cmd=None, env=None, cwd=None, extend_env=None, soft_quit="", autocomplete_server=False, **kwds): 59 | super(SubprocessRepl, self).__init__(encoding, **kwds) 60 | settings = load_settings('SublimeREPL.sublime-settings') 61 | 62 | if cmd[0] == "[unsupported]": 63 | raise Unsupported(cmd[1:]) 64 | 65 | self._autocomplete_server = None 66 | if autocomplete_server: 67 | self._autocomplete_server = AutocompleteServer(self, settings.get("autocomplete_server_ip")) 68 | self._autocomplete_server.start() 69 | 70 | env = self.env(env, extend_env, settings) 71 | env[b"SUBLIMEREPL_AC_PORT"] = str(self.autocomplete_server_port()).encode("utf-8") 72 | env[b"SUBLIMEREPL_AC_IP"] = settings.get("autocomplete_server_ip").encode("utf-8") 73 | 74 | if PY3: 75 | strings_env = {} 76 | for k, v in env.items(): 77 | strings_env[k.decode("utf-8")] = v.decode("utf-8") 78 | env = strings_env 79 | 80 | self._cmd = self.cmd(cmd, env) 81 | self._soft_quit = soft_quit 82 | self._killed = False 83 | self.popen = Popen( 84 | self._cmd, 85 | startupinfo=self.startupinfo(settings), 86 | creationflags=self.creationflags(settings), 87 | bufsize=1, 88 | cwd=self.cwd(cwd, settings), 89 | env=env, 90 | stderr=subprocess.STDOUT, 91 | stdin=subprocess.PIPE, 92 | stdout=subprocess.PIPE) 93 | 94 | if POSIX: 95 | flags = fcntl.fcntl(self.popen.stdout, fcntl.F_GETFL) 96 | fcntl.fcntl(self.popen.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) 97 | 98 | def autocomplete_server_port(self): 99 | if not self._autocomplete_server: 100 | return None 101 | return self._autocomplete_server.port() 102 | 103 | def autocomplete_available(self): 104 | if not self._autocomplete_server: 105 | return False 106 | return self._autocomplete_server.connected() 107 | 108 | def autocomplete_completions(self, whole_line, pos_in_line, prefix, whole_prefix, locations): 109 | return self._autocomplete_server.complete( 110 | whole_line=whole_line, 111 | pos_in_line=pos_in_line, 112 | prefix=prefix, 113 | whole_prefix=whole_prefix, 114 | locations=locations, 115 | ) 116 | 117 | def cmd(self, cmd, env): 118 | """On Linux and OSX just returns cmd, on windows it has to find 119 | executable in env because of this: http://bugs.python.org/issue8557""" 120 | if os.name != "nt": 121 | return cmd 122 | if isinstance(cmd, str): 123 | _cmd = [cmd] 124 | else: 125 | _cmd = cmd 126 | executable = win_find_executable(_cmd[0], env) 127 | if executable: 128 | _cmd[0] = executable 129 | return _cmd 130 | 131 | def cwd(self, cwd, settings): 132 | if cwd and os.path.exists(cwd): 133 | return cwd 134 | return None 135 | 136 | def getenv(self, settings): 137 | """Tries to get most appropriate environent, on windows 138 | it's os.environ.copy, but on other system's we'll 139 | try get values from login shell""" 140 | 141 | getenv_command = settings.get("getenv_command") 142 | if getenv_command and POSIX: 143 | try: 144 | output = subprocess.check_output(getenv_command) 145 | lines = output.decode("utf-8", errors="replace").splitlines() 146 | env = dict(line.split('=', 1) for line in lines) 147 | return env 148 | except: 149 | import traceback 150 | traceback.print_exc() 151 | error_message( 152 | "SublimeREPL: obtaining sane environment failed in getenv()\n" 153 | "Check console and 'getenv_command' setting \n" 154 | "WARN: Falling back to SublimeText environment") 155 | 156 | # Fallback to environ.copy() if not on POSIX or sane getenv failed 157 | return os.environ.copy() 158 | 159 | def env(self, env, extend_env, settings): 160 | updated_env = env if env else self.getenv(settings) 161 | default_extend_env = settings.get("default_extend_env") 162 | if default_extend_env: 163 | updated_env.update(self.interpolate_extend_env(updated_env, default_extend_env)) 164 | if extend_env: 165 | updated_env.update(self.interpolate_extend_env(updated_env, extend_env)) 166 | 167 | bytes_env = {} 168 | for k, v in list(updated_env.items()): 169 | try: 170 | enc_k = self.encoder(str(k))[0] 171 | enc_v = self.encoder(str(v))[0] 172 | except UnicodeDecodeError: 173 | continue #f*** it, we'll do it live 174 | else: 175 | bytes_env[enc_k] = enc_v 176 | return bytes_env 177 | 178 | def interpolate_extend_env(self, env, extend_env): 179 | """Interpolates (subst) values in extend_env. 180 | Mostly for path manipulation""" 181 | new_env = {} 182 | for key, val in list(extend_env.items()): 183 | new_env[key] = str(val).format(**env) 184 | return new_env 185 | 186 | def startupinfo(self, settings): 187 | startupinfo = None 188 | if os.name == 'nt': 189 | from .killableprocess import STARTUPINFO, STARTF_USESHOWWINDOW 190 | startupinfo = STARTUPINFO() 191 | startupinfo.dwFlags |= STARTF_USESHOWWINDOW 192 | startupinfo.wShowWindow |= 1 # SW_SHOWNORMAL 193 | return startupinfo 194 | 195 | def creationflags(self, settings): 196 | creationflags = 0 197 | if os.name == "nt": 198 | creationflags = 0x8000000 # CREATE_NO_WINDOW 199 | return creationflags 200 | 201 | def name(self): 202 | if self.external_id: 203 | return self.external_id 204 | if isinstance(self._cmd, str): 205 | return self._cmd 206 | return " ".join([str(x) for x in self._cmd]) 207 | 208 | def is_alive(self): 209 | return self.popen.poll() is None 210 | 211 | def read_bytes(self): 212 | out = self.popen.stdout 213 | if POSIX: 214 | while True: 215 | i, _, _ = select.select([out], [], []) 216 | if i: 217 | return out.read(4096) 218 | else: 219 | # this is windows specific problem, that you cannot tell if there 220 | # are more bytes ready, so we read only 1 at a times 221 | 222 | while True: 223 | byte = self.popen.stdout.read(1) 224 | if byte == b'\r': 225 | # f'in HACK, for \r\n -> \n translation on windows 226 | # I tried universal_endlines but it was pain and misery! :'( 227 | continue 228 | return byte 229 | 230 | 231 | 232 | def write_bytes(self, bytes): 233 | si = self.popen.stdin 234 | si.write(bytes) 235 | si.flush() 236 | 237 | def kill(self): 238 | self._killed = True 239 | self.write(self._soft_quit) 240 | self.popen.kill() 241 | 242 | def available_signals(self): 243 | signals = {} 244 | for k, v in list(signal.__dict__.items()): 245 | if not k.startswith("SIG"): 246 | continue 247 | signals[k] = v 248 | return signals 249 | 250 | def send_signal(self, sig): 251 | if sig == signal.SIGTERM: 252 | self._killed = True 253 | if self.is_alive(): 254 | self.popen.send_signal(sig) 255 | 256 | --------------------------------------------------------------------------------