|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="en-us"> |
| 3 | + <head> |
| 4 | + <meta charset="UTF-8"> |
| 5 | + <title>MagicPython by MagicStack</title> |
| 6 | + <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 7 | + <link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen"> |
| 8 | + <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'> |
| 9 | + <link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen"> |
| 10 | + <link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen"> |
| 11 | + </head> |
| 12 | + <body> |
| 13 | + <section class="page-header"> |
| 14 | + <h1 class="project-name">MagicPython</h1> |
| 15 | + <h2 class="project-tagline">Syntax highlighter for cutting edge Python for Sublime Text and Atom.</h2> |
| 16 | + <a href="https://github.com/MagicStack/MagicPython" class="btn">View on GitHub</a> |
| 17 | + <a href="https://github.com/MagicStack/MagicPython/zipball/master" class="btn">Download .zip</a> |
| 18 | + <a href="https://github.com/MagicStack/MagicPython/tarball/master" class="btn">Download .tar.gz</a> |
| 19 | + </section> |
| 20 | + |
| 21 | + <section class="main-content"> |
| 22 | + <p>This is a package with preferences and syntax highlighter for cutting edge |
| 23 | +Python 3 (although Python 2 is well supported too). The syntax is compatible |
| 24 | +with <a href="http://www.sublimetext.com">Sublime Text</a> and <a href="http://atom.io">Atom</a>. |
| 25 | +It is meant to be a drop-in replacement for the default Python package.</p> |
| 26 | + |
| 27 | +<p>The main motivation behind this package was the difficulty of using modern |
| 28 | +Python with other common syntax highlighters. They do a good job of the 90% of |
| 29 | +the language, but then fail on the nuances of some very useful, but often |
| 30 | +overlooked features. Function annotations tend to freak out the highlighters in |
| 31 | +various ways. Newly introduced keywords and magic methods are slow to be |
| 32 | +integrated. Another issue is string highlighting, where all raw strings are |
| 33 | +often assumed to be regular expressions or special markup used by <code>.format</code> is |
| 34 | +completely ignored. Bumping into all of these issues on daily basis eventually |
| 35 | +led to the creation of this package.</p> |
| 36 | + |
| 37 | +<h2> |
| 38 | +<a id="installation-instructions" class="anchor" href="#installation-instructions" aria-hidden="true"><span class="octicon octicon-link"></span></a>Installation Instructions</h2> |
| 39 | + |
| 40 | +<p>This is meant to be a drop-in replacement for the default Python package.</p> |
| 41 | + |
| 42 | +<p>In <strong>Atom</strong>, install the <code>MagicPython</code> package and disable the built-in |
| 43 | +<code>language-python</code> package.</p> |
| 44 | + |
| 45 | +<p>In <strong>Sublime Text</strong>, install <code>MagicPython</code> package via "Package Control" and |
| 46 | +disable the built-in <code>Python</code> package (using |
| 47 | +<code>Package Control -> Disable Package</code>, or directly by adding <code>"Python"</code> to |
| 48 | +<code>"ignored_packages"</code> in the settings file).</p> |
| 49 | + |
| 50 | +<p>Alternatively, the package can be installed manually in both editors:</p> |
| 51 | + |
| 52 | +<ul> |
| 53 | +<li>copy the MagicPython package into the Sublime/Atom user packages directory;</li> |
| 54 | +<li>disable Python package;</li> |
| 55 | +<li>enjoy.</li> |
| 56 | +</ul> |
| 57 | + |
| 58 | +<h2> |
| 59 | +<a id="changes-and-improvements" class="anchor" href="#changes-and-improvements" aria-hidden="true"><span class="octicon octicon-link"></span></a>Changes and Improvements</h2> |
| 60 | + |
| 61 | +<p>Overall, the central idea is that it should be easy to notice something odd or |
| 62 | +special about the code. Odd or special doesn't necessarily mean incorrect, but |
| 63 | +certainly worth the explicit attention.</p> |
| 64 | + |
| 65 | +<h3> |
| 66 | +<a id="annotations" class="anchor" href="#annotations" aria-hidden="true"><span class="octicon octicon-link"></span></a>Annotations</h3> |
| 67 | + |
| 68 | +<p>Annotations should not break the highlighting. They should be no more difficult |
| 69 | +to read at a glance than other code or comments.</p> |
| 70 | + |
| 71 | +<p>A typical case is having a string annotation that spans several lines by using |
| 72 | +implicit string concatenation. Multi-line strings are suboptimal for use in |
| 73 | +annotations as it may be highly undesirable to have odd indentation and extra |
| 74 | +whitespace in the annotation string. Of course, there is no problem using line |
| 75 | +continuation or even having comments mixed in with implicit string |
| 76 | +concatenation. All of these will be highlighted as you'd expect in any other |
| 77 | +place in the code.</p> |
| 78 | + |
| 79 | +<div class="highlight highlight-source-python"><pre><span class="pl-k">def</span> <span class="pl-en">some_func</span>(<span class="pl-smi">a</span>, <span class="pl-c"># nothing fancy here, yet</span> |
| 80 | + |
| 81 | + b: 'Annotation: ' <span class="pl-c"># implicitly</span> |
| 82 | + '"foo" for <span class="pl-smi">Foo</span>, ' <span class="pl-c"># concatenated</span> |
| 83 | + '"bar" for <span class="pl-smi">Bar</span>, ' <span class="pl-c"># annotation</span> |
| 84 | + '"other" otherwise'='otherwise'):</pre></div> |
| 85 | + |
| 86 | +<p>A more advanced use case for annotations is to actually have complex expressions |
| 87 | +in them, such as lambda functions, tuples, lists, dicts, sets, comprehensions. |
| 88 | +Admittedly, all of these might be less frequently used, but when they are, you |
| 89 | +can rely on them being highlighted normally in all their glorious details.</p> |
| 90 | + |
| 91 | +<div class="highlight highlight-source-python"><pre><span class="pl-c"># no reason why this should cause the highlighter to break</span> |
| 92 | +<span class="pl-c">#</span> |
| 93 | +<span class="pl-k">def</span> <span class="pl-en">some_func</span>(a: |
| 94 | + <span class="pl-c"># annotation starts here</span> |
| 95 | + lambda <span class="pl-smi">x</span><span class="pl-k">=</span><span class="pl-c1">None</span>: |
| 96 | + {key: <span class="pl-smi">val</span> |
| 97 | + for <span class="pl-smi">key</span>, val <span class="pl-smi">in</span> |
| 98 | + (x if x is not None else []) |
| 99 | + } |
| 100 | + <span class="pl-c"># annotation ends here and below is the default for 'a'</span> |
| 101 | + =42):</pre></div> |
| 102 | + |
| 103 | +<p>Result annotations are handled as any other expression would be. No reason to |
| 104 | +worry that the body of the function would look messed up.</p> |
| 105 | + |
| 106 | +<div class="highlight highlight-source-python"><pre><span class="pl-c"># no reason why this should cause the highlighter to break</span> |
| 107 | +<span class="pl-c">#</span> |
| 108 | +<span class="pl-k">def</span> <span class="pl-en">some_func</span>() -> { |
| 109 | + 'Some', <span class="pl-c"># comments</span> |
| 110 | + 'valid', <span class="pl-c"># are</span> |
| 111 | + 'expression' <span class="pl-c"># good</span> |
| 112 | + }:</pre></div> |
| 113 | + |
| 114 | +<h3> |
| 115 | +<a id="strings" class="anchor" href="#strings" aria-hidden="true"><span class="octicon octicon-link"></span></a>Strings</h3> |
| 116 | + |
| 117 | +<p>Strings are used in many different ways for processing and presenting data. |
| 118 | +Making the highlighter more friendly towards these uses can help you concentrate |
| 119 | +your efforts on what matters rather than visual parsing.</p> |
| 120 | + |
| 121 | +<p>Raw strings are often interpreted as regular expressions. This is a bit of a |
| 122 | +problem, because depending on the application this may actually not be the most |
| 123 | +common case. Raw strings can simply be the input to some other processor, in |
| 124 | +which case regexp-specific highlighting is really hindering the overall |
| 125 | +readability. MagicPython follows a convention that a lower-case <code>r</code> prefix means |
| 126 | +a regexp string, but an upper-case <code>R</code> prefix means just a raw string with no |
| 127 | +special regexp semantics. This convention holds true for all of the legal |
| 128 | +combinations of prefixes. As always the syntax is biased towards Python 3, thus |
| 129 | +it will mark Pyhton-2-only prefixes (i.e. variations of <code>ur</code>) as deprecated.</p> |
| 130 | + |
| 131 | +<p>String formatting is often only supported for '%-style formatting', however, the |
| 132 | +recommended and more readable syntax used by <code>.format</code> is ignored. The benefits |
| 133 | +of using simple and readable <code>{key}</code> replacement fields are hindered by the fact |
| 134 | +that in a complex or long string expression it may not be easily apparent what |
| 135 | +parameters will actually be needed by <code>.format</code>. This is why MagicPyhton |
| 136 | +highlights both kinds of string formatting syntax within the appropriate string |
| 137 | +types (bytes don't have a <code>.format</code> method in Python 3, so they don't get the |
| 138 | +special highlighting for it, raw and unicode strings do). Additionally, the |
| 139 | +highlighter also validates that the formatting is following the correct syntax. |
| 140 | +It can help noticing an error in complex formatting expressions early.</p> |
| 141 | + |
| 142 | +<h3> |
| 143 | +<a id="numeric-literals" class="anchor" href="#numeric-literals" aria-hidden="true"><span class="octicon octicon-link"></span></a>Numeric literals</h3> |
| 144 | + |
| 145 | +<p>Most numbers are just regular decimal constants, but any time that octal, |
| 146 | +binary, hexadecimal or complex numbers are used it's worth noting that they are |
| 147 | +of a special type. Highlighting of Python 2 'L' integers is also supported.</p> |
| 148 | + |
| 149 | +<h3> |
| 150 | +<a id="python-35-features" class="anchor" href="#python-35-features" aria-hidden="true"><span class="octicon octicon-link"></span></a>Python 3.5 features</h3> |
| 151 | + |
| 152 | +<p>New keywords <code>async</code> and <code>await</code> are properly highlighted. Currently, these |
| 153 | +keywords are new and are not yet reserved, so the Python interpreter will allow |
| 154 | +using them as variable names. However, <code>async</code> and <code>await</code> are not recommended |
| 155 | +to be used as variable, class, function or module names. Introduced by |
| 156 | +<a href="https://www.python.org/dev/peps/pep-0492/">PEP 492</a> in Python 3.5, they will |
| 157 | +become proper keywords in Python 3.7. It is very important that the highlighter |
| 158 | +shows their proper status when they are used as function parameter names, as |
| 159 | +that could otherwise be unnoticed and lead to very messy debugging down the |
| 160 | +road.</p> |
| 161 | + |
| 162 | +<h3> |
| 163 | +<a id="built-ins-and-magic-methods" class="anchor" href="#built-ins-and-magic-methods" aria-hidden="true"><span class="octicon octicon-link"></span></a>Built-ins and Magic Methods</h3> |
| 164 | + |
| 165 | +<p>Various built-in types, classes, functions, as well as magic methods are all |
| 166 | +highlighted. Specifically, they are highlighted when they appear as names in |
| 167 | +user definitions. Although it is not an error to have classes and functions that |
| 168 | +mask the built-ins, it is certainly worth drawing attention to, so that masking |
| 169 | +becomes a deliberate rather than accidental act.</p> |
| 170 | + |
| 171 | +<p>Highlighting built-ins in class inheritance list makes it slightly more obvious |
| 172 | +where standard classes are extended. It is also easier to notice some typos |
| 173 | +(have you ever typed <code>Excepiton</code>?) a little earlier.</p> |
| 174 | + |
| 175 | +<h3> |
| 176 | +<a id="parameters-and-arguments" class="anchor" href="#parameters-and-arguments" aria-hidden="true"><span class="octicon octicon-link"></span></a>Parameters and Arguments</h3> |
| 177 | + |
| 178 | +<p>MagicPython highlights keywords when they are used as parameter/argument names. |
| 179 | +This was mentioned for the case of <code>async</code> and <code>await</code>, but it holds true for |
| 180 | +all other keywords. Although the Python interpreter will produce an appropriate |
| 181 | +error message when reserved keywords are used as identifier names, it's still |
| 182 | +worth showing them early, to spare even this small debugging effort.</p> |
| 183 | + |
| 184 | +<h2> |
| 185 | +<a id="development" class="anchor" href="#development" aria-hidden="true"><span class="octicon octicon-link"></span></a>Development</h2> |
| 186 | + |
| 187 | +<p>You need <code>npm</code> and <code>node.js</code> to work on MagicPython.</p> |
| 188 | + |
| 189 | +<ul> |
| 190 | +<li>clone the repository</li> |
| 191 | +<li>run <code>make</code> to build the local development environment</li> |
| 192 | +<li>run <code>make release</code> to build the syntax packages for Sublime Text and Atom |
| 193 | +(running <code>make test</code> also generates the "release" packages)</li> |
| 194 | +</ul> |
| 195 | + |
| 196 | +<p>Please note that we have some unit tests for the syntax scoping. We will be |
| 197 | +expanding and updating our test corpus. This allows us to trust that tiny |
| 198 | +inconsistencies will not easily creep in as we update the syntax and fix bugs. |
| 199 | +Use <code>make test</code> to run the tests regularly while updating the syntax spec. |
| 200 | +Currently the test files have two parts to them, separated by 3 empty newlines: |
| 201 | +the code to be scoped and the spec that the result must match.</p> |
| 202 | + |
| 203 | +<p>If you intend to submit a pull request, please follow the following guidelines:</p> |
| 204 | + |
| 205 | +<ul> |
| 206 | +<li>keep code lines under 80 characters in length, it improves readability</li> |
| 207 | +<li> |
| 208 | +<p>please <em>do</em> use multi-line regular expressions for any non-trivial cases like:</p> |
| 209 | + |
| 210 | +<ul> |
| 211 | +<li>the regexp contains a mix of escaped and unescaped braces/parentheses</li> |
| 212 | +<li>the regexp has several <code>|</code> in it</li> |
| 213 | +<li>the regexp has several pairs of parentheses, especially nested ones</li> |
| 214 | +<li>or the regexp is simply longer than 35 characters</li> |
| 215 | +</ul> |
| 216 | +</li> |
| 217 | +<li><p>always run <code>make test</code> to ensure that your changes didn't have unexpected side |
| 218 | +effects</p></li> |
| 219 | +<li>update unit tests and add new ones if needed, keeping the test cases short |
| 220 | +whenever possible</li> |
| 221 | +</ul> |
| 222 | + |
| 223 | + <footer class="site-footer"> |
| 224 | + <span class="site-footer-owner"><a href="https://github.com/MagicStack/MagicPython">MagicPython</a> is maintained by <a href="https://github.com/MagicStack">MagicStack</a>.</span> |
| 225 | + |
| 226 | + <span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a> using the <a href="https://github.com/jasonlong/cayman-theme">Cayman theme</a> by <a href="https://twitter.com/jasonlong">Jason Long</a>.</span> |
| 227 | + </footer> |
| 228 | + |
| 229 | + </section> |
| 230 | + |
| 231 | + |
| 232 | + </body> |
| 233 | +</html> |
0 commit comments