Skip to content

Instantly share code, notes, and snippets.

@MacHu-GWU
Last active July 21, 2021 01:26
Embed
What would you like to do?
Sublime text settings sync
// These settings override both User and Default settings for the Bash syntax
{
"translate_tabs_to_spaces": true
}
[
// Auto-pair stars
{ "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|>|$)", "match_all": true },
{ "key": "preceding_text", "operator": "not_regex_contains", "operand": "[*a-zA-Z0-9_]$", "match_all": true },
{ "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true }
]
},
{ "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }
]
},
{ "keys": ["*"], "command": "move", "args": {"by": "characters", "forward": true}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "following_text", "operator": "regex_contains", "operand": "^*", "match_all": true },
{ "key": "selector", "operator": "not_equal", "operand": "punctuation.definition.string.begin", "match_all": true },
{ "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true },
]
},
{ "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete Left Right.sublime-macro"}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "preceding_text", "operator": "regex_contains", "operand": "*$", "match_all": true },
{ "key": "following_text", "operator": "regex_contains", "operand": "^*", "match_all": true },
{ "key": "selector", "operator": "not_equal", "operand": "punctuation.definition.string.begin", "match_all": true },
{ "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true },
]
},
// Auto-pair `
{ "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`$0`"}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|>|$)", "match_all": true },
{ "key": "preceding_text", "operator": "not_regex_contains", "operand": "[`a-zA-Z0-9_]$", "match_all": true },
{ "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true }
]
},
{ "keys": ["`"], "command": "insert_snippet", "args": {"contents": "`${0:$SELECTION}`"}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true }
]
},
{ "keys": ["`"], "command": "move", "args": {"by": "characters", "forward": true}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true },
{ "key": "selector", "operator": "not_equal", "operand": "punctuation.definition.string.begin", "match_all": true },
{ "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true },
]
},
{ "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete Left Right.sublime-macro"}, "context":
[
{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
{ "key": "preceding_text", "operator": "regex_contains", "operand": "`$", "match_all": true },
{ "key": "following_text", "operator": "regex_contains", "operand": "^`", "match_all": true },
{ "key": "selector", "operator": "not_equal", "operand": "punctuation.definition.string.begin", "match_all": true },
{ "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true },
]
},
{ "keys": ["super+shift+alt+u"], "command": "upper_case" },
{ "keys": ["super+shift+alt+l"], "command": "lower_case" },
{ "keys": ["super+shift+alt+t"], "command": "title_case" },
{ "keys": ["super+shift+alt+s"], "command": "swap_case" },
// Previous Tab, Next Tab
{ "keys": ["ctrl+pageup"], "command": "prev_view" },
{ "keys": ["ctrl+pagedown"], "command": "next_view" },
// Fix Home and End Behavior in MacOS
{ "keys": ["home"], "command": "move_to", "args": {"to": "bol"} },
{ "keys": ["end"], "command": "move_to", "args": {"to": "eol"} },
{ "keys": ["shift+end"], "command": "move_to", "args": {"to": "eol", "extend": true} },
{ "keys": ["shift+home"], "command": "move_to", "args": {"to": "bol", "extend": true } },
{ "keys": ["ctrl+home"], "command": "move_to", "args": {"to": "bof"} },
{ "keys": ["ctrl+end"], "command": "move_to", "args": {"to": "eof"} },
{ "keys": ["ctrl+shift+home"], "command": "move_to", "args": {"to": "bof", "extend": true} },
{ "keys": ["ctrl+shift+end"], "command": "move_to", "args": {"to": "eof", "extend": true} },
]
// These settings override both User and Default settings for the Groovy syntax
{
"tab_size": 2,
"translate_tabs_to_spaces": true
}
{
"rulers": // 标尺的位置, 可以有多个标尺
[
100,
200
],
"tab_size": 4, // tab键等效的空格数
"translate_tabs_to_spaces": true, // 自动将tab键转化为空格
"word_wrap": true, // 是否打开自动断行
"wrap_width": 200, // 自动断行的位置
}
{
"rulers": // 标尺的位置, 可以有多个标尺
[
80
],
"tab_size": 4, // tab键等效的空格数
"translate_tabs_to_spaces": true, // 自动将tab键转化为空格
"word_wrap": false, // 是否打开自动断行
}
{
"automatically_update_executable": true
}
{
"report_errors": false,
"show_help_dialog": false
}
{
"rulers": // 标尺的位置, 可以有多个标尺
[
80
],
"tab_size": 4, // tab键等效的空格数
"translate_tabs_to_spaces": true, // 自动将tab键转化为空格
"word_wrap": true, // 是否打开自动断行
}
<snippet>
<scope>source.shell</scope>
<description>Bash Shebang</description>
<tabTrigger>shebangbash</tabTrigger>
<content><![CDATA[
#!/bin/bash
# -*- coding: utf-8 -*-
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Header 1</description>
<tabTrigger>h1</tabTrigger>
<content><![CDATA[
${1:header1}
==============================================================================
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Header 2</description>
<tabTrigger>h2</tabTrigger>
<content><![CDATA[
${1:header2}
------------------------------------------------------------------------------
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Header 3</description>
<tabTrigger>h3</tabTrigger>
<content><![CDATA[
${1:header3}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Header 4</description>
<tabTrigger>h4</tabTrigger>
<content><![CDATA[
${1:header4}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Header 5</description>
<tabTrigger>h5</tabTrigger>
<content><![CDATA[
${1:header5}
******************************************************************************
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Header 6</description>
<tabTrigger>h6</tabTrigger>
<content><![CDATA[
${1:header6}
##############################################################################
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Header 7</description>
<tabTrigger>h7</tabTrigger>
<content><![CDATA[
${1:header7}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
]]></content>
</snippet>
<snippet>
<scope>text</scope>
<description>Utf8 Encoding Shebang</description>
<tabTrigger>utf8shebang</tabTrigger>
<content><![CDATA[
# -*- coding: utf-8 -*-
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>Doc String for Method</description>
<tabTrigger>docstrmethod</tabTrigger>
<content><![CDATA[
"""
${1:title}
${2:description}
:param parameter1: parameter1_description.
:type parameter1: parameter1_type
:returns: return_description
:rtype: return_type
"""
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>Add Doc String</description>
<tabTrigger>docstr</tabTrigger>
<content><![CDATA[
"""
${1:docstring}
"""
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>from __future__ import xxx</description>
<tabTrigger>impfuture</tabTrigger>
<content><![CDATA[
from __future__ import (
print_function, unicode_literals, absolute_import,
division, generators,
)
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>import numpy, pandas</description>
<tabTrigger>impnumpypandas</tabTrigger>
<content><![CDATA[
import numpy as np, pandas as pd
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>import pytest</description>
<tabTrigger>imppytest</tabTrigger>
<content><![CDATA[
import pytest
from pytest import approx
if __name__ == "__main__":
import os
pytest.main([os.path.basename(__file__), "--tb=native", "-s"])
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>import numpy, pandas</description>
<tabTrigger>impsqlalchemycore</tabTrigger>
<content><![CDATA[
from sqlalchemy import create_engine, MetaData, Table, Column
from sqlalchemy import String, Integer, Float, Date, DateTime, LargeBinary
from sqlalchemy import select, and_, or_, not_, func
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>Doc String for Method</description>
<tabTrigger>nocover</tabTrigger>
<content><![CDATA[
# pragma: no cover
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>Python Shebang</description>
<tabTrigger>shebangpython</tabTrigger>
<content><![CDATA[
#!/usr/bin/env python
# -*- coding: utf-8 -*-
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>Run unittest in this direcotry</description>
<tabTrigger>testall</tabTrigger>
<content><![CDATA[
# -*- coding: utf-8 -*-
if __name__ == "__main__":
import pytest
pytest.main(["-s", "--tb=native"])
]]></content>
</snippet>
<snippet>
<scope>source.python</scope>
<description>Run unittest in this file</description>
<tabTrigger>testthis</tabTrigger>
<content><![CDATA[
# -*- coding: utf-8 -*-
import pytest
from pytest import raises, approx
if __name__ == "__main__":
import os
basename = os.path.basename(__file__)
pytest.main([basename, "-s", "--tb=native"])
]]></content>
</snippet>

Edit Your Own Code Snippet and Activate them in Sublime Text, Atom and PyCharm

You could write your own snippet in this format, fill in {{ scope }}, {{ description }}, {{ trigger }}, {{ content }}, following This Guide), and save with {{ unique-snippet-name.sublime-snippet }}:

<snippet>
    <scope>{{ scope }}</scope>
    <description>{{ description }}</description>
    <tabTrigger>{{ trigger }}</tabTrigger>
    <content><![CDATA[
{{ content }}
]]></content>
</snippet>

Make sure your snippet files are under MySnippets Folder.

Then just run transform.py in Python (Python27, 34, 35, 36) file. Your snippet will be available to use in Sublime Text, Atom and PyCharm.

Dependencies:

  • lxml
  • beautifulsoup4
  • pathlib_mate
<snippet>
<scope>text.restructuredtext</scope>
<description>Auto Number Sections</description>
<tabTrigger>sectnum</tabTrigger>
<content><![CDATA[
.. sectnum::
:depth: 3
:prefix: ${1:Prefix}
:surfix: ${2:Surfix}
:start: 1
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Bash Code</description>
<tabTrigger>codebash</tabTrigger>
<content><![CDATA[
.. code-block:: bash
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>CoffeeScript Code</description>
<tabTrigger>codecoffeescript</tabTrigger>
<content><![CDATA[
.. code-block:: coffeescript
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Html Code</description>
<tabTrigger>codehtml</tabTrigger>
<content><![CDATA[
.. code-block:: html
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>JavaScript Code</description>
<tabTrigger>codejs</tabTrigger>
<content><![CDATA[
.. code-block:: javascript
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Jinja2 Code</description>
<tabTrigger>codejinja2</tabTrigger>
<content><![CDATA[
.. code-block:: jinja
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Makefile Code</description>
<tabTrigger>codemakefile</tabTrigger>
<content><![CDATA[
.. code-block:: Makefiles
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Python Code</description>
<tabTrigger>codepython</tabTrigger>
<content><![CDATA[
.. code-block:: python
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>RestructuredText Code</description>
<tabTrigger>coderest</tabTrigger>
<content><![CDATA[
.. code-block:: ReST
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Ruby Code</description>
<tabTrigger>coderuby</tabTrigger>
<content><![CDATA[
.. code-block:: ruby
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Scala Code</description>
<tabTrigger>codescala</tabTrigger>
<content><![CDATA[
.. code-block:: scala
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>SQL Code</description>
<tabTrigger>codesql</tabTrigger>
<content><![CDATA[
.. code-block:: SQL
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Windows Batch File Code</description>
<tabTrigger>codebatch</tabTrigger>
<content><![CDATA[
.. code-block:: batch
${1:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Syntax Highlighted Code</description>
<tabTrigger>code</tabTrigger>
<content><![CDATA[
.. code-block:: ${1:language}
${2:code}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Footer of the page</description>
<tabTrigger>footer</tabTrigger>
<content><![CDATA[
.. footer:: ${1:Footer of the page}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Footnote</description>
<tabTrigger>footnote</tabTrigger>
<content><![CDATA[
.. [#] ${1:description}.
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Header of the page</description>
<tabTrigger>header</tabTrigger>
<content><![CDATA[
.. header:: ${1:Header of the page}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Styled Image</description>
<tabTrigger>imagestyled</tabTrigger>
<content><![CDATA[
.. image:: ${1:url}
:alt: ${2:Image Not Found}
:height: ${3:600} px
:width: ${4:800} px
:align: ${5:left right or center}
:target: ${6:target}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Image</description>
<tabTrigger>image</tabTrigger>
<content><![CDATA[
.. image:: ${1:url}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Styled Image</description>
<tabTrigger>imgstyled</tabTrigger>
<content><![CDATA[
.. image:: ${1:url}
:alt: ${2:Image Not Found}
:height: ${3:600} px
:width: ${4:800} px
:align: ${5:left right or center}
:target: ${6:target}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Image</description>
<tabTrigger>img</tabTrigger>
<content><![CDATA[
.. image:: ${1:url}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Includee External File</description>
<tabTrigger>include</tabTrigger>
<content><![CDATA[
.. include:: ${1:path}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>List Table</description>
<tabTrigger>ltable</tabTrigger>
<content><![CDATA[
.. list-table:: ${1:Title of the table}
:widths: 10 10 10
:header-rows: 1
* - ${2:Header1}
- ${3:Header2}
- ${4:Header3}
* - ${5:Value1}
- ${6:Value2}
- ${7:Value3}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Auto Table of content</description>
<tabTrigger>autotoc</tabTrigger>
<content><![CDATA[
.. autotoctree::
:maxdepth: 1
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Centered Boldfaced Line of Text</description>
<tabTrigger>centered</tabTrigger>
<content><![CDATA[
.. centered:: ${1:message}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Deprecated</description>
<tabTrigger>deprecated</tabTrigger>
<content><![CDATA[
.. deprecated:: ${1:verion}
${2:message}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Horizontal Compact List</description>
<tabTrigger>hlist</tabTrigger>
<content><![CDATA[
.. hlist::
:columns: ${1:n_columns}
* ${2:item1}
* ${3:item2}
* ${4:item3}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Note</description>
<tabTrigger>note</tabTrigger>
<content><![CDATA[
.. note::
${1:message}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>See Also</description>
<tabTrigger>seealso</tabTrigger>
<content><![CDATA[
.. seealso::
${1:message}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Version Added</description>
<tabTrigger>versionadded</tabTrigger>
<content><![CDATA[
.. versionadded:: ${1:verion}
${2:message}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Version Changed</description>
<tabTrigger>versionchanged</tabTrigger>
<content><![CDATA[
.. versionchanged:: ${1:verion}
${2:message}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Warning</description>
<tabTrigger>warning</tabTrigger>
<content><![CDATA[
.. warning::
${1:message}
]]></content>
</snippet>
<snippet>
<scope>text.restructuredtext</scope>
<description>Table of content</description>
<tabTrigger>toc</tabTrigger>
<content><![CDATA[
.. contents::
]]></content>
</snippet>
# -*- coding: utf-8 -*-
r"""
Author: Sanhe Hu
CopyRight: MIT 2017
Allow user to read sublime snippet, and transform into Atom/PyCharm snippet.
Where to put snippet:
Sublime Text
------------
put this ``MySnippets`` folder under:
- Windows: ``C:\Users\<your-username>\AppData\Roaming\Sublime Text 3\Packages\User\``
- MacOS: ``/Users/<your-username>/Library/Application Support/Sublime Text 3/Packages/User/``
Atom
----
Open ``Atom`` -> ``Snippet``, edit this file.
- Window: ``C:\Users\<your-username>\.atom/snippets.cson``.
- MacOS: ``/Users/<your-username>/.atom/snippets.cson``.
- Linux: ``Unknown``.
Ref: https://github.com/atom/snippets
PyCharm
-------
create a xml file ``<Template-Group-Name>.xml``, let's say ``User.xml``, edit
this file and put it under
- Window: ``C:\Users\<your-username>\.PyCharm<version>\config\templates``.
- MacOS: ``/Users/<your-username>/Library/Preferences/PyCharmCE2<version>/templates``.
- Linux: ``/.PyCharmXX/config/templates``.
Ref: https://www.jetbrains.com/help/pycharm/project-and-ide-settings.html
"""
from __future__ import (
print_function, absolute_import,
division, generators,
)
import os
import shutil
import platform
import re
import lxml.etree as ET
from pathlib_mate import Path
from bs4 import BeautifulSoup
is_Windows, is_MacOS, is_Linux = False, False, False
system_name = platform.system()
if system_name == "Windows":
is_Windows = True
elif system_name == "Darwin":
is_MacOS = True
elif system_name == "Linux":
is_Linux = True
else:
raise Exception("Unknown Operation System!")
user_dir = os.path.expanduser("~")
def read(path):
"""
Read utf-8 pure text file.
"""
with open(path, "rb") as f:
return f.read().decode("utf-8").replace("\r\n", "\n")
def write(content, path):
"""
Write string to utf-8 pure text file
"""
with open(path, "wb") as f:
return f.write(content.encode("utf-8"))
snippet_dir = Path(__file__).parent
"""
Source snippet directory.
"""
def reset_test_file():
"""
Delete content of all test file
"""
for p in snippet_dir.select_file(lambda p: p.fname == "test"):
write(" ", p.abspath)
reset_test_file()
def extract_by_prefix_surfix(text, prefix, surfix, minlen=None, maxlen=None,
include=False):
"""Extract the text in between a prefix and surfix. It use non-greedy match.
:param text: text body
:type text: str
:param prefix: the prefix
:type prefix: str
:param surfix: the surfix
:type surfix: str
:param minlen: the min matched string length
:type minlen: int
:param maxlen: the max matched string length
:type maxlen: int
:param include: whether if include prefix and surfix
:type include: bool
"""
if minlen is None:
minlen = 0
if maxlen is None:
maxlen = 2 ** 30
pattern = r"""(?<=%s)[\s\S]{%s,%s}?(?=%s)""" % (
prefix, minlen, maxlen, surfix)
if include:
return [prefix + s + surfix for s in re.findall(pattern, text)]
else:
return re.findall(pattern, text)
sublime_tpl = \
'''
<snippet>
<scope>{scope}</scope>
<description>{description}</description>
<tabTrigger>{trigger}</tabTrigger>
<content><![CDATA[
{content}
]]></content>
</snippet>
'''.strip()
atom_snippet_tpl = \
'''
'{description}':
'prefix': '{trigger}'
'body': """
{body}
"""
'''.replace('"', "'").strip()
atom_tpl = \
"""
'{scope}':
{list_of_snippet_cson}
""".strip()
pycharm_scope_mapper = {
"source.python": "Python",
"source.shell": "Bash",
"text.restructuredtext": "OTHER",
"text": "OTHER",
}
def indent_n_space(text, n):
"""
Add indent for each line.
"""
indent = " " * n
return "\n".join([indent + line for line in text.split("\n")])
def find_sublime_snippets_dir():
r"""
Find Sublime snippets directory.
put this ``MySnippets`` folder under:
- Windows: ``C:\Users\<your-username>\AppData\Roaming\Sublime Text 3\Packages\User\``
- MacOS: ``/Users/<your-username>/Library/Application Support/Sublime Text 3/Packages/User/``
"""
if is_Windows:
return Path(user_dir,
"AppData", "Roaming",
"Sublime Text 3", "Packages", "User").abspath
elif is_MacOS:
return Path(user_dir,
"Library", "Application Support",
"Sublime Text 3", "Packages", "User").abspath
elif is_Linux:
raise NotImplementedError
def find_atom_snippets_dir():
r"""
Find Atom snippets directory.
Open ``Atom`` -> ``Snippet``, edit this file.
- Window: ``C:\Users\<your-username>\.atom/snippets.cson``.
- MacOS: ``/Users/<your-username>/.atom/snippets.cson``.
- Linux: ``Unknown``.
"""
return Path(user_dir, ".atom").abspath
def find_pycharm_snippets_dir():
r"""
Find PyCharm snippets directory.
create a xml file ``<Template-Group-Name>.xml``, let's say ``User.xml``, edit
this file and put it under
Window: ``C:\Users\<your-username>\.PyCharm<version>\config\templates``.
MacOS: ``/Users/<your-username>/Library/Preferences/PyCharmCE2<version>/templates``.
Linux: ``/.PyCharmXX/config/templates``.
Ref: https://www.jetbrains.com/help/pycharm/project-and-ide-settings.html
"""
l = list()
if is_Windows:
for p in Path(user_dir).select_dir(
filters=lambda p: p.basename.startswith(".PyCharm"),
recursive=False):
l.append(Path(p, "config", "templates").abspath)
elif is_MacOS:
preference_dir = Path(user_dir, "Library", "Preferences")
for p in Path(preference_dir).select_dir(
filters=lambda p: p.basename.startswith("PyCharm"),
recursive=False):
l.append(Path(p, "templates").abspath)
elif is_Linux:
for p in Path("/").select_dir(
filters=lambda p: p.basename.startswith(".PyCharm"),
recursive=False):
l.append(Path(p, "config", "templates").abspath)
return l
class Snippet(object):
"""
Represent a Snippet
:param scope: available for which type of file.
:param description: help message to descript this snippet.
:param trigger: text to trigger this snippet.
:param content: content of this snippet, written in CoffeeScript.
:param fname: filename of this snippet.
"""
sublime_tpl = sublime_tpl
atom_tpl = atom_tpl
def __init__(self, scope, description, trigger, content, args, fname=None):
self.scope = scope
self.description = description
self.trigger = trigger
self.content = content
self.args = args
if fname is None:
self.fname = self.description.replace(" ", "-")
@property
def sublime_scope(self):
"""
Return its Sublime scope.
"""
return self.scope
@property
def atom_scope(self):
"""
Return its Atom scope.
"""
return "." + self.scope
@property
def pycharm_scope(self):
"""
Return its PyCharm scope.
"""
return pycharm_scope_mapper[self.scope]
def to_sublime_snippet(self):
"""
Export as sublime snippet xml format.
"""
xml = self.sublime_tpl.format(
scope=self.sublime_scope,
description=self.description,
trigger=self.trigger,
content=self.content,
)
return xml
def to_atom_cson(self):
"""
Export as atom cson snippet format.
Example:
.. code-block: CoffeeScript
'Footer':
'prefix': 'footer'
'body': '''
.. footer::
'''
"""
cson = atom_snippet_tpl.format(
description=self.description,
trigger=self.trigger,
body=indent_n_space(self.content, 4)
)
cson = indent_n_space(cson, 2)
return cson
@classmethod
def to_atom_snippet(cls, snippet_list):
"""
Export to atom snippet cson file.
"""
snippet_by_scope = dict()
# group by scope
for snippet in snippet_list:
try:
snippet_by_scope[snippet.atom_scope].append(snippet)
except:
snippet_by_scope[snippet.atom_scope] = [snippet, ]
l = list()
for scope, snippet_list in snippet_by_scope.items():
scope_snippet = atom_tpl.format(
scope=scope,
list_of_snippet_cson="\n\n".join(
[snippet.to_atom_cson() for snippet in snippet_list]
)
)
l.append(scope_snippet)
return "\n".join(l)
@property
def pycharm_content(self):
"""
Convert CoffeeScript snippet language to PyCharm snippet language.
- in CoffeeScript: [${1:item} for $1 in ${2:iterable}]
- in PyCharm: [$item$ for $item$ in $iterable$]
"""
content = self.content
for i, arg in enumerate(self.args):
i += 1
content = content.replace(
"$%s" % i,
"${%s:%s}" % (i, arg),
)
for i, arg in enumerate(self.args):
i += 1
content = content.replace(
"${%s:%s}" % (i, arg),
"$%s$" % arg.replace(" ", "_").replace("-", "_"),
)
return content
@classmethod
def to_pycharm_snippet(cls, snippet_list, group_name="User"):
"""
Example:
.. code-block: xml
<templateSet group="PythonUser">
<template name="class" value="class $class$($object$):&#10; &quot;&quot;&quot;$cls_doc$&quot;&quot;&quot;&#10;&#10; def __init__(self,$args$):&#10; &quot;&quot;&quot;Constructor for $class$&quot;&quot;&quot;&#10; $END$" description="" toReformat="false" toShortenFQNames="true">
<variable name="class" expression="" defaultValue="" alwaysStopAt="true" />
<variable name="object" expression="" defaultValue="" alwaysStopAt="true" />
<variable name="cls_doc" expression="" defaultValue="" alwaysStopAt="true" />
<variable name="args" expression="" defaultValue="" alwaysStopAt="true" />
<context>
<option name="Python" value="true" />
</context>
</template>
...
</templateSet>
"""
templateSet = ET.Element("templateSet", group=group_name)
# template = ET.SubElement(templateSet, "template")
for snippet in snippet_list:
if snippet.scope not in pycharm_scope_mapper:
continue
template = ET.SubElement(
templateSet, "template",
name=snippet.trigger,
description=snippet.description,
value=snippet.pycharm_content,
toReformat="false",
toShortenFQNames="true",
)
for arg in snippet.args:
variable = ET.SubElement(
template, "variable",
name=arg.replace(" ", "_").replace("-", "_"),
expression="",
defaultValue='"%s"' % arg,
alwaysStopAt="true",
)
context = ET.SubElement(template, "context")
option = ET.SubElement(
context, "option",
name=snippet.pycharm_scope,
value="true",
)
xml = ET.tostring(
templateSet, pretty_print=True, encoding="utf-8").decode("utf-8")
return xml
@classmethod
def write_sublime_snippet(cls):
"""
Write to Sublime Snippet.
"""
src = snippet_dir.abspath
dst = Path(find_sublime_snippets_dir(), snippet_dir.basename).abspath
try:
shutil.rmtree(dst)
except:
pass
try:
print("Copy Snippet to %s ..." % dst)
shutil.copytree(src, dst)
print(" Success!")
except Exception as e:
print(" Failed to write Sublime snippet! %r" % e)
@classmethod
def write_atom_snippet(cls, snippet_list):
"""
Write Sublime Snippet to PyCharm Live Templates XML.
"""
cson = cls.to_atom_snippet(snippet_list)
abspath = Path(find_atom_snippets_dir(), "snippet.cson").abspath
try:
print("Copy Snippet to %s ..." % abspath)
write(cson, abspath)
print(" Success!")
except Exception as e:
print(" Failed to write Atom snippet! %r" % e)
@classmethod
def write_pycharm_snippet_xml(cls, snippet_list, group_name):
"""
Write Sublime Snippet to PyCharm Live Templates XML.
"""
for pycharm_snippet_dir in find_pycharm_snippets_dir():
xml = cls.to_pycharm_snippet(snippet_list, group_name)
abspath = Path(pycharm_snippet_dir, "%s.xml" % group_name).abspath
try:
os.makedirs(pycharm_snippet_dir)
except:
pass
try:
print("Copy Snippet to %s ..." % abspath)
write(xml, abspath)
print(" Success!")
except Exception as e:
print(" Failed to write PyCharm snippet! %r" % e)
@classmethod
def from_sublime_snippet_xml(cls, xml, fname):
"""
Read snippet from sublime snippet xml.
"""
soup = BeautifulSoup(xml, "xml")
scope = soup.snippet.scope.text
description = soup.snippet.description.text
trigger = soup.snippet.tabTrigger.text
content = extract_by_prefix_surfix(
xml, prefix="<!\[CDATA\[\n", surfix="\n\]\]>", include=False)[0]
args = list()
for place_holder in re.findall("\$\{\d*:[\s\S]+?\}", content):
arg = place_holder[:-1].split(":", 1)[1]
args.append(arg)
snippet = cls(
scope=scope,
description=description,
trigger=trigger,
content=content,
args=args,
fname=p.fname,
)
return snippet
if __name__ == "__main__":
snippet_list = list()
for p in snippet_dir.select_by_ext(".sublime-snippet"):
xml = read(p.abspath)
snippet = Snippet.from_sublime_snippet_xml(xml, p.fname)
snippet_list.append(snippet)
Snippet.write_sublime_snippet()
Snippet.write_atom_snippet(snippet_list)
Snippet.write_pycharm_snippet_xml(snippet_list, "User")
# cson = Snippet.to_atom_snippet(snippet_list)
# print(cson)
xml = Snippet.to_pycharm_snippet(snippet_list)
print(xml)
{
"bootstrapped": true,
"in_process_packages":
[
],
"installed_packages":
[
"A File Icon",
"Anaconda",
"Bash Build System",
"Boxy Theme",
"BracketHighlighter",
"CForm",
"Dockerfile Syntax Highlighting",
"FileDiffs",
"HTML-CSS-JS Prettify",
"JSONComma",
"MarkdownEditing",
"OmniMarkupPreviewer",
"Package Control",
"Pretty JSON",
"Python PEP8 Autoformat",
"RestructuredText Improved",
"SideBarEnhancements",
"Sync Settings",
"Terraform",
"TrailingSpaces",
],
}
{
"bold_folder_labels": true,
"color_scheme": "Packages/Color Scheme - Default/Monokai.sublime-color-scheme",
"draw_white_space": "all",
"fade_fold_buttons": false,
"font_size": 13,
"highlight_line": true,
"highlight_modified_tabs": true,
"ignored_packages":
[
"RestructuredText",
"Vintage",
],
"indent_guide_options":
[
"draw_normal",
"draw_active"
],
"jsoncomma_on_save": true,
"line_padding_bottom": 0,
"line_padding_top": 0,
"open_files_in_new_window": false,
"preview_on_click": true,
"remember_open_files": true,
"rulers":
[
100
],
"spell_check": true,
"tab_completion": false,
"tab_size": 4,
"theme": "Boxy Monokai.sublime-theme",
"translate_tabs_to_spaces": false,
"word_wrap": true,
"wrap_width": 100,
}
{
"ignored_packages":
[
"Boxy Theme",
"BracketHighlighter",
"Vintage"
]
}
{
"rulers": // 标尺的位置, 可以有多个标尺
[
80
],
"tab_size": 4, // tab键等效的空格数
"translate_tabs_to_spaces": true, // 自动将tab键转化为空格
"word_wrap": false, // 是否打开自动断行
}
{
"cmd": ["/Users/sanhehu/.pyenv/versions/2.7.13/bin/python", "-u", "$file"],
"env": {"LANG": "en_US.UTF-8"},
}
{
"cmd": ["/Users/sanhehu/.pyenv/versions/3.5.3/bin/python", "-u", "$file"],
"env": {"LANG": "en_US.UTF-8"},
}
{
"cmd": ["/Users/sanhehu/.pyenv/versions/3.6.2/bin/python", "-u", "$file"],
"env": {"LANG": "en_US.UTF-8"}
}
{
"spell_check": true, // 是否检查拼写
"tab_size": 4, // 制表符等于多少个空格
"translate_tabs_to_spaces": true // 自动将tab键转化为空格
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment