diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f3ba45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*.cache diff --git a/ASP/ASP.tmLanguage.cache b/ASP/ASP.tmLanguage.cache deleted file mode 100644 index c0d2381..0000000 Binary files a/ASP/ASP.tmLanguage.cache and /dev/null differ diff --git a/ASP/HTML-ASP.tmLanguage.cache b/ASP/HTML-ASP.tmLanguage.cache deleted file mode 100644 index 9804707..0000000 Binary files a/ASP/HTML-ASP.tmLanguage.cache and /dev/null differ diff --git a/ActionScript/ActionScript.tmLanguage.cache b/ActionScript/ActionScript.tmLanguage.cache deleted file mode 100644 index e3f4fa6..0000000 Binary files a/ActionScript/ActionScript.tmLanguage.cache and /dev/null differ diff --git a/Alignment/Alignment.pyc b/Alignment/Alignment.pyc deleted file mode 100644 index 44d6536..0000000 Binary files a/Alignment/Alignment.pyc and /dev/null differ diff --git a/AppleScript/AppleScript.tmLanguage.cache b/AppleScript/AppleScript.tmLanguage.cache deleted file mode 100644 index 9a1137c..0000000 Binary files a/AppleScript/AppleScript.tmLanguage.cache and /dev/null differ diff --git a/Batch File/Batch File.tmLanguage.cache b/Batch File/Batch File.tmLanguage.cache deleted file mode 100644 index 8253453..0000000 Binary files a/Batch File/Batch File.tmLanguage.cache and /dev/null differ diff --git a/C#/Build.tmLanguage.cache b/C#/Build.tmLanguage.cache deleted file mode 100644 index 7ce69df..0000000 Binary files a/C#/Build.tmLanguage.cache and /dev/null differ diff --git a/C#/C#.tmLanguage.cache b/C#/C#.tmLanguage.cache deleted file mode 100644 index 17ef45d..0000000 Binary files a/C#/C#.tmLanguage.cache and /dev/null differ diff --git a/C++/C++.tmLanguage.cache b/C++/C++.tmLanguage.cache deleted file mode 100644 index 29d6b93..0000000 Binary files a/C++/C++.tmLanguage.cache and /dev/null differ diff --git a/C++/C.tmLanguage.cache b/C++/C.tmLanguage.cache deleted file mode 100644 index d03c9c6..0000000 Binary files a/C++/C.tmLanguage.cache and /dev/null differ diff --git a/C++/Comments (C++).tmPreferences.cache b/C++/Comments (C++).tmPreferences.cache deleted file mode 100644 index 57cff8b..0000000 Binary files a/C++/Comments (C++).tmPreferences.cache and /dev/null differ diff --git a/C++/Indentation Rules.tmPreferences.cache b/C++/Indentation Rules.tmPreferences.cache deleted file mode 100644 index 7611b43..0000000 Binary files a/C++/Indentation Rules.tmPreferences.cache and /dev/null differ diff --git a/C++/Symbol List - Indent Class Methods.tmPreferences.cache b/C++/Symbol List - Indent Class Methods.tmPreferences.cache deleted file mode 100644 index f7eff23..0000000 Binary files a/C++/Symbol List - Indent Class Methods.tmPreferences.cache and /dev/null differ diff --git a/C++/Symbol List - Prefix Banner Items.tmPreferences.cache b/C++/Symbol List - Prefix Banner Items.tmPreferences.cache deleted file mode 100644 index c321af3..0000000 Binary files a/C++/Symbol List - Prefix Banner Items.tmPreferences.cache and /dev/null differ diff --git a/CSS/CSS.tmLanguage.cache b/CSS/CSS.tmLanguage.cache deleted file mode 100644 index 9e7c964..0000000 Binary files a/CSS/CSS.tmLanguage.cache and /dev/null differ diff --git a/CSS/Comments.tmPreferences.cache b/CSS/Comments.tmPreferences.cache deleted file mode 100644 index 740ab8b..0000000 Binary files a/CSS/Comments.tmPreferences.cache and /dev/null differ diff --git a/CSS/Symbol List Group.tmPreferences.cache b/CSS/Symbol List Group.tmPreferences.cache deleted file mode 100644 index 4557a38..0000000 Binary files a/CSS/Symbol List Group.tmPreferences.cache and /dev/null differ diff --git a/CSS/Symbol List.tmPreferences.cache b/CSS/Symbol List.tmPreferences.cache deleted file mode 100644 index a1caaed..0000000 Binary files a/CSS/Symbol List.tmPreferences.cache and /dev/null differ diff --git a/Clojure/Clojure.tmLanguage.cache b/Clojure/Clojure.tmLanguage.cache deleted file mode 100644 index d53e7fa..0000000 Binary files a/Clojure/Clojure.tmLanguage.cache and /dev/null differ diff --git a/Clojure/Comment.tmPreferences.cache b/Clojure/Comment.tmPreferences.cache deleted file mode 100644 index 164b6fc..0000000 Binary files a/Clojure/Comment.tmPreferences.cache and /dev/null differ diff --git a/Clojure/Symbol List.tmPreferences.cache b/Clojure/Symbol List.tmPreferences.cache deleted file mode 100644 index da742bf..0000000 Binary files a/Clojure/Symbol List.tmPreferences.cache and /dev/null differ diff --git a/Color Scheme - Default/All Hallow's Eve.tmTheme.cache b/Color Scheme - Default/All Hallow's Eve.tmTheme.cache deleted file mode 100644 index 509af32..0000000 Binary files a/Color Scheme - Default/All Hallow's Eve.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Amy.tmTheme.cache b/Color Scheme - Default/Amy.tmTheme.cache deleted file mode 100644 index 63d1536..0000000 Binary files a/Color Scheme - Default/Amy.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Blackboard.tmTheme.cache b/Color Scheme - Default/Blackboard.tmTheme.cache deleted file mode 100644 index 4f5cb10..0000000 Binary files a/Color Scheme - Default/Blackboard.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Cobalt.tmTheme.cache b/Color Scheme - Default/Cobalt.tmTheme.cache deleted file mode 100644 index 88437d1..0000000 Binary files a/Color Scheme - Default/Cobalt.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Dawn.tmTheme.cache b/Color Scheme - Default/Dawn.tmTheme.cache deleted file mode 100644 index b17078a..0000000 Binary files a/Color Scheme - Default/Dawn.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Eiffel.tmTheme.cache b/Color Scheme - Default/Eiffel.tmTheme.cache deleted file mode 100644 index 37f2c07..0000000 Binary files a/Color Scheme - Default/Eiffel.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Espresso Libre.tmTheme.cache b/Color Scheme - Default/Espresso Libre.tmTheme.cache deleted file mode 100644 index 9e09be9..0000000 Binary files a/Color Scheme - Default/Espresso Libre.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/IDLE.tmTheme.cache b/Color Scheme - Default/IDLE.tmTheme.cache deleted file mode 100644 index 4cf30a4..0000000 Binary files a/Color Scheme - Default/IDLE.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/LAZY.tmTheme.cache b/Color Scheme - Default/LAZY.tmTheme.cache deleted file mode 100644 index be82dd7..0000000 Binary files a/Color Scheme - Default/LAZY.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Mac Classic.tmTheme.cache b/Color Scheme - Default/Mac Classic.tmTheme.cache deleted file mode 100644 index 5d91c95..0000000 Binary files a/Color Scheme - Default/Mac Classic.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/MagicWB (Amiga).tmTheme.cache b/Color Scheme - Default/MagicWB (Amiga).tmTheme.cache deleted file mode 100644 index 2711e53..0000000 Binary files a/Color Scheme - Default/MagicWB (Amiga).tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Monokai Bright.tmTheme.cache b/Color Scheme - Default/Monokai Bright.tmTheme.cache deleted file mode 100644 index f8e29e9..0000000 Binary files a/Color Scheme - Default/Monokai Bright.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Monokai.tmTheme.cache b/Color Scheme - Default/Monokai.tmTheme.cache deleted file mode 100644 index b93f0e6..0000000 Binary files a/Color Scheme - Default/Monokai.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Pastels on Dark.tmTheme.cache b/Color Scheme - Default/Pastels on Dark.tmTheme.cache deleted file mode 100644 index f0a2400..0000000 Binary files a/Color Scheme - Default/Pastels on Dark.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Slush & Poppies.tmTheme.cache b/Color Scheme - Default/Slush & Poppies.tmTheme.cache deleted file mode 100644 index 94f345d..0000000 Binary files a/Color Scheme - Default/Slush & Poppies.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Solarized (Dark).tmTheme.cache b/Color Scheme - Default/Solarized (Dark).tmTheme.cache deleted file mode 100644 index 3b5cb5c..0000000 Binary files a/Color Scheme - Default/Solarized (Dark).tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Solarized (Light).tmTheme.cache b/Color Scheme - Default/Solarized (Light).tmTheme.cache deleted file mode 100644 index 511938b..0000000 Binary files a/Color Scheme - Default/Solarized (Light).tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/SpaceCadet.tmTheme.cache b/Color Scheme - Default/SpaceCadet.tmTheme.cache deleted file mode 100644 index ebb2a43..0000000 Binary files a/Color Scheme - Default/SpaceCadet.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Sunburst.tmTheme.cache b/Color Scheme - Default/Sunburst.tmTheme.cache deleted file mode 100644 index 8bb1ebf..0000000 Binary files a/Color Scheme - Default/Sunburst.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/Zenburnesque.tmTheme.cache b/Color Scheme - Default/Zenburnesque.tmTheme.cache deleted file mode 100644 index dd7de4a..0000000 Binary files a/Color Scheme - Default/Zenburnesque.tmTheme.cache and /dev/null differ diff --git a/Color Scheme - Default/iPlastic.tmTheme.cache b/Color Scheme - Default/iPlastic.tmTheme.cache deleted file mode 100644 index 3cff790..0000000 Binary files a/Color Scheme - Default/iPlastic.tmTheme.cache and /dev/null differ diff --git a/D/Comments.tmPreferences.cache b/D/Comments.tmPreferences.cache deleted file mode 100644 index e728535..0000000 Binary files a/D/Comments.tmPreferences.cache and /dev/null differ diff --git a/D/D.tmLanguage.cache b/D/D.tmLanguage.cache deleted file mode 100644 index 49a6727..0000000 Binary files a/D/D.tmLanguage.cache and /dev/null differ diff --git a/D/Indentation Rules.tmPreferences.cache b/D/Indentation Rules.tmPreferences.cache deleted file mode 100644 index d7693db..0000000 Binary files a/D/Indentation Rules.tmPreferences.cache and /dev/null differ diff --git a/D/Symbol List-Method-Constructor.tmPreferences.cache b/D/Symbol List-Method-Constructor.tmPreferences.cache deleted file mode 100644 index 7dae094..0000000 Binary files a/D/Symbol List-Method-Constructor.tmPreferences.cache and /dev/null differ diff --git a/Default/Find Results.hidden-tmLanguage.cache b/Default/Find Results.hidden-tmLanguage.cache deleted file mode 100644 index 9afac60..0000000 Binary files a/Default/Find Results.hidden-tmLanguage.cache and /dev/null differ diff --git a/Default/Ignored Packages.cache b/Default/Ignored Packages.cache deleted file mode 100644 index 27b92a5..0000000 --- a/Default/Ignored Packages.cache +++ /dev/null @@ -1 +0,0 @@ -["Vintage"] \ No newline at end of file diff --git a/Default/Meta Info Summary.cache b/Default/Meta Info Summary.cache deleted file mode 100644 index bc17893..0000000 Binary files a/Default/Meta Info Summary.cache and /dev/null differ diff --git a/Default/Miscellaneous.tmPreferences.cache b/Default/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 886762a..0000000 Binary files a/Default/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/Default/Startup.cache b/Default/Startup.cache deleted file mode 100644 index 58e7fec..0000000 Binary files a/Default/Startup.cache and /dev/null differ diff --git a/Default/Symbol List.tmPreferences.cache b/Default/Symbol List.tmPreferences.cache deleted file mode 100644 index 8ee76a7..0000000 Binary files a/Default/Symbol List.tmPreferences.cache and /dev/null differ diff --git a/Default/Syntax Summary.cache b/Default/Syntax Summary.cache deleted file mode 100644 index c37769e..0000000 Binary files a/Default/Syntax Summary.cache and /dev/null differ diff --git a/Default/comment.pyc b/Default/comment.pyc deleted file mode 100644 index ce0e14e..0000000 Binary files a/Default/comment.pyc and /dev/null differ diff --git a/Default/copy_path.pyc b/Default/copy_path.pyc deleted file mode 100644 index 790886a..0000000 Binary files a/Default/copy_path.pyc and /dev/null differ diff --git a/Default/delete_word.pyc b/Default/delete_word.pyc deleted file mode 100644 index f46354f..0000000 Binary files a/Default/delete_word.pyc and /dev/null differ diff --git a/Default/detect_indentation.pyc b/Default/detect_indentation.pyc deleted file mode 100644 index 45c82b0..0000000 Binary files a/Default/detect_indentation.pyc and /dev/null differ diff --git a/Default/duplicate_line.pyc b/Default/duplicate_line.pyc deleted file mode 100644 index b8d2e1a..0000000 Binary files a/Default/duplicate_line.pyc and /dev/null differ diff --git a/Default/echo.pyc b/Default/echo.pyc deleted file mode 100644 index 98d902e..0000000 Binary files a/Default/echo.pyc and /dev/null differ diff --git a/Default/exec.pyc b/Default/exec.pyc deleted file mode 100644 index e91a9e9..0000000 Binary files a/Default/exec.pyc and /dev/null differ diff --git a/Default/find_under_expand.pyc b/Default/find_under_expand.pyc deleted file mode 100644 index c451f6c..0000000 Binary files a/Default/find_under_expand.pyc and /dev/null differ diff --git a/Default/fold.pyc b/Default/fold.pyc deleted file mode 100644 index 6151797..0000000 Binary files a/Default/fold.pyc and /dev/null differ diff --git a/Default/font.pyc b/Default/font.pyc deleted file mode 100644 index cd8f7fe..0000000 Binary files a/Default/font.pyc and /dev/null differ diff --git a/Default/goto_line.pyc b/Default/goto_line.pyc deleted file mode 100644 index afbeeba..0000000 Binary files a/Default/goto_line.pyc and /dev/null differ diff --git a/Default/indentation.pyc b/Default/indentation.pyc deleted file mode 100644 index 8a7608b..0000000 Binary files a/Default/indentation.pyc and /dev/null differ diff --git a/Default/kill_ring.pyc b/Default/kill_ring.pyc deleted file mode 100644 index 526910d..0000000 Binary files a/Default/kill_ring.pyc and /dev/null differ diff --git a/Default/mark.pyc b/Default/mark.pyc deleted file mode 100644 index a0f8677..0000000 Binary files a/Default/mark.pyc and /dev/null differ diff --git a/Default/new_templates.pyc b/Default/new_templates.pyc deleted file mode 100644 index bed220b..0000000 Binary files a/Default/new_templates.pyc and /dev/null differ diff --git a/Default/open_file_settings.pyc b/Default/open_file_settings.pyc deleted file mode 100644 index 9d398ea..0000000 Binary files a/Default/open_file_settings.pyc and /dev/null differ diff --git a/Default/paragraph.pyc b/Default/paragraph.pyc deleted file mode 100644 index 2ed0c29..0000000 Binary files a/Default/paragraph.pyc and /dev/null differ diff --git a/Default/save_on_focus_lost.pyc b/Default/save_on_focus_lost.pyc deleted file mode 100644 index 1def175..0000000 Binary files a/Default/save_on_focus_lost.pyc and /dev/null differ diff --git a/Default/scroll.pyc b/Default/scroll.pyc deleted file mode 100644 index ee8fa53..0000000 Binary files a/Default/scroll.pyc and /dev/null differ diff --git a/Default/send2trash/__init__.pyc b/Default/send2trash/__init__.pyc deleted file mode 100644 index f13ca9c..0000000 Binary files a/Default/send2trash/__init__.pyc and /dev/null differ diff --git a/Default/send2trash/plat_win.pyc b/Default/send2trash/plat_win.pyc deleted file mode 100644 index 3383dd6..0000000 Binary files a/Default/send2trash/plat_win.pyc and /dev/null differ diff --git a/Default/side_bar.pyc b/Default/side_bar.pyc deleted file mode 100644 index 916b65d..0000000 Binary files a/Default/side_bar.pyc and /dev/null differ diff --git a/Default/sort.pyc b/Default/sort.pyc deleted file mode 100644 index 87f3b64..0000000 Binary files a/Default/sort.pyc and /dev/null differ diff --git a/Default/swap_line.pyc b/Default/swap_line.pyc deleted file mode 100644 index 639361b..0000000 Binary files a/Default/swap_line.pyc and /dev/null differ diff --git a/Default/switch_file.pyc b/Default/switch_file.pyc deleted file mode 100644 index 861860f..0000000 Binary files a/Default/switch_file.pyc and /dev/null differ diff --git a/Default/transform.pyc b/Default/transform.pyc deleted file mode 100644 index 591c31c..0000000 Binary files a/Default/transform.pyc and /dev/null differ diff --git a/Default/transpose.pyc b/Default/transpose.pyc deleted file mode 100644 index a3e467f..0000000 Binary files a/Default/transpose.pyc and /dev/null differ diff --git a/Default/trim_trailing_white_space.pyc b/Default/trim_trailing_white_space.pyc deleted file mode 100644 index 3ab1160..0000000 Binary files a/Default/trim_trailing_white_space.pyc and /dev/null differ diff --git a/Diff/Diff.tmLanguage.cache b/Diff/Diff.tmLanguage.cache deleted file mode 100644 index 48958fd..0000000 Binary files a/Diff/Diff.tmLanguage.cache and /dev/null differ diff --git a/Diff/diff.pyc b/Diff/diff.pyc deleted file mode 100644 index ff83e1d..0000000 Binary files a/Diff/diff.pyc and /dev/null differ diff --git a/Drupal Snippets/package-metadata.json b/Drupal Snippets/package-metadata.json index e8fea20..f9c1b18 100644 --- a/Drupal Snippets/package-metadata.json +++ b/Drupal Snippets/package-metadata.json @@ -1 +1 @@ -{"url": "https://github.com/juhasz/drupal_sublime-snippets", "version": "2012.01.22.20.31.41", "description": "Drupal snippets for Sublime Editor, converted from Vim snipMate drupal-snippets"} \ No newline at end of file +{"url": "https://github.com/juhasz/drupal_sublime-snippets", "version": "2012.01.22.23.31.41", "description": "Drupal snippets for Sublime Editor, converted from Vim snipMate drupal-snippets"} \ No newline at end of file diff --git a/Erlang/Comments.tmPreferences.cache b/Erlang/Comments.tmPreferences.cache deleted file mode 100644 index 72dd0cc..0000000 Binary files a/Erlang/Comments.tmPreferences.cache and /dev/null differ diff --git a/Erlang/Erlang.tmLanguage.cache b/Erlang/Erlang.tmLanguage.cache deleted file mode 100644 index b2e06dd..0000000 Binary files a/Erlang/Erlang.tmLanguage.cache and /dev/null differ diff --git a/Erlang/Function Symbols.tmPreferences.cache b/Erlang/Function Symbols.tmPreferences.cache deleted file mode 100644 index b087f55..0000000 Binary files a/Erlang/Function Symbols.tmPreferences.cache and /dev/null differ diff --git a/Erlang/HTML (Erlang).tmLanguage.cache b/Erlang/HTML (Erlang).tmLanguage.cache deleted file mode 100644 index 64fd925..0000000 Binary files a/Erlang/HTML (Erlang).tmLanguage.cache and /dev/null differ diff --git a/Erlang/Indentation Rules.tmPreferences.cache b/Erlang/Indentation Rules.tmPreferences.cache deleted file mode 100644 index ae87a09..0000000 Binary files a/Erlang/Indentation Rules.tmPreferences.cache and /dev/null differ diff --git a/Erlang/Macro Symbols.tmPreferences.cache b/Erlang/Macro Symbols.tmPreferences.cache deleted file mode 100644 index b72d70c..0000000 Binary files a/Erlang/Macro Symbols.tmPreferences.cache and /dev/null differ diff --git a/Erlang/Module Symbols.tmPreferences.cache b/Erlang/Module Symbols.tmPreferences.cache deleted file mode 100644 index adc29d9..0000000 Binary files a/Erlang/Module Symbols.tmPreferences.cache and /dev/null differ diff --git a/Erlang/Record Symbols.tmPreferences.cache b/Erlang/Record Symbols.tmPreferences.cache deleted file mode 100644 index 10bb8b5..0000000 Binary files a/Erlang/Record Symbols.tmPreferences.cache and /dev/null differ diff --git a/Erlang/Symbol Overrides.tmPreferences.cache b/Erlang/Symbol Overrides.tmPreferences.cache deleted file mode 100644 index 4ffe2c8..0000000 Binary files a/Erlang/Symbol Overrides.tmPreferences.cache and /dev/null differ diff --git a/Go/Comments.tmPreferences.cache b/Go/Comments.tmPreferences.cache deleted file mode 100644 index e3dae2d..0000000 Binary files a/Go/Comments.tmPreferences.cache and /dev/null differ diff --git a/Go/Go.tmLanguage.cache b/Go/Go.tmLanguage.cache deleted file mode 100644 index 0e3d391..0000000 Binary files a/Go/Go.tmLanguage.cache and /dev/null differ diff --git a/Go/Indentation Rules.tmPreferences.cache b/Go/Indentation Rules.tmPreferences.cache deleted file mode 100644 index 76fa6b4..0000000 Binary files a/Go/Indentation Rules.tmPreferences.cache and /dev/null differ diff --git a/Graphviz/DOT.tmLanguage.cache b/Graphviz/DOT.tmLanguage.cache deleted file mode 100644 index 5b1240e..0000000 Binary files a/Graphviz/DOT.tmLanguage.cache and /dev/null differ diff --git a/Groovy/Groovy.tmLanguage.cache b/Groovy/Groovy.tmLanguage.cache deleted file mode 100644 index 735653c..0000000 Binary files a/Groovy/Groovy.tmLanguage.cache and /dev/null differ diff --git a/Groovy/Symbol List%3A Class Variables.tmPreferences.cache b/Groovy/Symbol List%3A Class Variables.tmPreferences.cache deleted file mode 100644 index 6938ba9..0000000 Binary files a/Groovy/Symbol List%3A Class Variables.tmPreferences.cache and /dev/null differ diff --git a/Groovy/Symbol List%3A Classes.tmPreferences.cache b/Groovy/Symbol List%3A Classes.tmPreferences.cache deleted file mode 100644 index 983e8b3..0000000 Binary files a/Groovy/Symbol List%3A Classes.tmPreferences.cache and /dev/null differ diff --git a/Groovy/Symbol List%3A Methods.tmPreferences.cache b/Groovy/Symbol List%3A Methods.tmPreferences.cache deleted file mode 100644 index f3a253c..0000000 Binary files a/Groovy/Symbol List%3A Methods.tmPreferences.cache and /dev/null differ diff --git a/Groovy/Symbol List%3A Variables.tmPreferences.cache b/Groovy/Symbol List%3A Variables.tmPreferences.cache deleted file mode 100644 index bd33a52..0000000 Binary files a/Groovy/Symbol List%3A Variables.tmPreferences.cache and /dev/null differ diff --git a/HTML/Comments.tmPreferences.cache b/HTML/Comments.tmPreferences.cache deleted file mode 100644 index 3e18286..0000000 Binary files a/HTML/Comments.tmPreferences.cache and /dev/null differ diff --git a/HTML/HTML.tmLanguage.cache b/HTML/HTML.tmLanguage.cache deleted file mode 100644 index ce6b94c..0000000 Binary files a/HTML/HTML.tmLanguage.cache and /dev/null differ diff --git a/HTML/Symbol List - ID.tmPreferences.cache b/HTML/Symbol List - ID.tmPreferences.cache deleted file mode 100644 index 246c870..0000000 Binary files a/HTML/Symbol List - ID.tmPreferences.cache and /dev/null differ diff --git a/HTML/encode_html_entities.pyc b/HTML/encode_html_entities.pyc deleted file mode 100644 index a171985..0000000 Binary files a/HTML/encode_html_entities.pyc and /dev/null differ diff --git a/HTML/html_completions.pyc b/HTML/html_completions.pyc deleted file mode 100644 index 98dd2bf..0000000 Binary files a/HTML/html_completions.pyc and /dev/null differ diff --git a/Haskell/Comments.tmPreferences.cache b/Haskell/Comments.tmPreferences.cache deleted file mode 100644 index fb75b7e..0000000 Binary files a/Haskell/Comments.tmPreferences.cache and /dev/null differ diff --git a/Haskell/Haskell.tmLanguage.cache b/Haskell/Haskell.tmLanguage.cache deleted file mode 100644 index 803814e..0000000 Binary files a/Haskell/Haskell.tmLanguage.cache and /dev/null differ diff --git a/Haskell/Indent Patterns.tmPreferences.cache b/Haskell/Indent Patterns.tmPreferences.cache deleted file mode 100644 index 1d82332..0000000 Binary files a/Haskell/Indent Patterns.tmPreferences.cache and /dev/null differ diff --git a/Haskell/Literate Haskell.tmLanguage.cache b/Haskell/Literate Haskell.tmLanguage.cache deleted file mode 100644 index 085a694..0000000 Binary files a/Haskell/Literate Haskell.tmLanguage.cache and /dev/null differ diff --git a/Haskell/Symbol List.tmPreferences.cache b/Haskell/Symbol List.tmPreferences.cache deleted file mode 100644 index 067fd06..0000000 Binary files a/Haskell/Symbol List.tmPreferences.cache and /dev/null differ diff --git a/Java/Comments.tmPreferences.cache b/Java/Comments.tmPreferences.cache deleted file mode 100644 index 842b0b5..0000000 Binary files a/Java/Comments.tmPreferences.cache and /dev/null differ diff --git a/Java/Indentation Rules.tmPreferences.cache b/Java/Indentation Rules.tmPreferences.cache deleted file mode 100644 index f005cc5..0000000 Binary files a/Java/Indentation Rules.tmPreferences.cache and /dev/null differ diff --git a/Java/Java Server Pages (JSP).tmLanguage.cache b/Java/Java Server Pages (JSP).tmLanguage.cache deleted file mode 100644 index 875d2b6..0000000 Binary files a/Java/Java Server Pages (JSP).tmLanguage.cache and /dev/null differ diff --git a/Java/Java.tmLanguage.cache b/Java/Java.tmLanguage.cache deleted file mode 100644 index e04ddfd..0000000 Binary files a/Java/Java.tmLanguage.cache and /dev/null differ diff --git a/Java/JavaDoc.tmLanguage.cache b/Java/JavaDoc.tmLanguage.cache deleted file mode 100644 index 5f237e5..0000000 Binary files a/Java/JavaDoc.tmLanguage.cache and /dev/null differ diff --git a/Java/JavaProperties.tmLanguage.cache b/Java/JavaProperties.tmLanguage.cache deleted file mode 100644 index ceea5aa..0000000 Binary files a/Java/JavaProperties.tmLanguage.cache and /dev/null differ diff --git a/Java/Symbol List%3A Classes.tmPreferences.cache b/Java/Symbol List%3A Classes.tmPreferences.cache deleted file mode 100644 index 786170c..0000000 Binary files a/Java/Symbol List%3A Classes.tmPreferences.cache and /dev/null differ diff --git a/Java/Symbol List%3A Inner Class Methods.tmPreferences.cache b/Java/Symbol List%3A Inner Class Methods.tmPreferences.cache deleted file mode 100644 index 5497bbe..0000000 Binary files a/Java/Symbol List%3A Inner Class Methods.tmPreferences.cache and /dev/null differ diff --git a/Java/Symbol List%3A Inner Classes.tmPreferences.cache b/Java/Symbol List%3A Inner Classes.tmPreferences.cache deleted file mode 100644 index 1d04b5a..0000000 Binary files a/Java/Symbol List%3A Inner Classes.tmPreferences.cache and /dev/null differ diff --git a/Java/Symbol List%3A Inner Inner Class Methods.tmPreferences.cache b/Java/Symbol List%3A Inner Inner Class Methods.tmPreferences.cache deleted file mode 100644 index 3999fbf..0000000 Binary files a/Java/Symbol List%3A Inner Inner Class Methods.tmPreferences.cache and /dev/null differ diff --git a/Java/Symbol List%3A Inner Inner Classes.tmPreferences.cache b/Java/Symbol List%3A Inner Inner Classes.tmPreferences.cache deleted file mode 100644 index d1ff68a..0000000 Binary files a/Java/Symbol List%3A Inner Inner Classes.tmPreferences.cache and /dev/null differ diff --git a/Java/Symbol List%3A Method.tmPreferences.cache b/Java/Symbol List%3A Method.tmPreferences.cache deleted file mode 100644 index 3a7a179..0000000 Binary files a/Java/Symbol List%3A Method.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/Comments.tmPreferences.cache b/JavaScript/Comments.tmPreferences.cache deleted file mode 100644 index bba47b6..0000000 Binary files a/JavaScript/Comments.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/JSON.tmLanguage.cache b/JavaScript/JSON.tmLanguage.cache deleted file mode 100644 index c2a42dc..0000000 Binary files a/JavaScript/JSON.tmLanguage.cache and /dev/null differ diff --git a/JavaScript/JavaScript Indent.tmPreferences.cache b/JavaScript/JavaScript Indent.tmPreferences.cache deleted file mode 100644 index c482a57..0000000 Binary files a/JavaScript/JavaScript Indent.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/JavaScript.tmLanguage.cache b/JavaScript/JavaScript.tmLanguage.cache deleted file mode 100644 index fbe3d1d..0000000 Binary files a/JavaScript/JavaScript.tmLanguage.cache and /dev/null differ diff --git a/JavaScript/Symbol List Banned.tmPreferences.cache b/JavaScript/Symbol List Banned.tmPreferences.cache deleted file mode 100644 index 65943ec..0000000 Binary files a/JavaScript/Symbol List Banned.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/Symbol List Class.tmPreferences.cache b/JavaScript/Symbol List Class.tmPreferences.cache deleted file mode 100644 index d31e750..0000000 Binary files a/JavaScript/Symbol List Class.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/Symbol List Function.tmPreferences.cache b/JavaScript/Symbol List Function.tmPreferences.cache deleted file mode 100644 index f48a04b..0000000 Binary files a/JavaScript/Symbol List Function.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/Symbol List Instance.tmPreferences.cache b/JavaScript/Symbol List Instance.tmPreferences.cache deleted file mode 100644 index 7fb6c88..0000000 Binary files a/JavaScript/Symbol List Instance.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/Symbol List Sub 1.tmPreferences.cache b/JavaScript/Symbol List Sub 1.tmPreferences.cache deleted file mode 100644 index 94d526e..0000000 Binary files a/JavaScript/Symbol List Sub 1.tmPreferences.cache and /dev/null differ diff --git a/JavaScript/Symbol List Sub 2.tmPreferences.cache b/JavaScript/Symbol List Sub 2.tmPreferences.cache deleted file mode 100644 index 2a1b7c3..0000000 Binary files a/JavaScript/Symbol List Sub 2.tmPreferences.cache and /dev/null differ diff --git a/LaTeX/Bibtex.tmLanguage.cache b/LaTeX/Bibtex.tmLanguage.cache deleted file mode 100644 index 620eb7a..0000000 Binary files a/LaTeX/Bibtex.tmLanguage.cache and /dev/null differ diff --git a/LaTeX/Comments.tmPreferences.cache b/LaTeX/Comments.tmPreferences.cache deleted file mode 100644 index 34b9944..0000000 Binary files a/LaTeX/Comments.tmPreferences.cache and /dev/null differ diff --git a/LaTeX/LaTeX Beamer.tmLanguage.cache b/LaTeX/LaTeX Beamer.tmLanguage.cache deleted file mode 100644 index 2f3eec9..0000000 Binary files a/LaTeX/LaTeX Beamer.tmLanguage.cache and /dev/null differ diff --git a/LaTeX/LaTeX Log.tmLanguage.cache b/LaTeX/LaTeX Log.tmLanguage.cache deleted file mode 100644 index 71eb94f..0000000 Binary files a/LaTeX/LaTeX Log.tmLanguage.cache and /dev/null differ diff --git a/LaTeX/LaTeX Memoir.tmLanguage.cache b/LaTeX/LaTeX Memoir.tmLanguage.cache deleted file mode 100644 index 3e936b5..0000000 Binary files a/LaTeX/LaTeX Memoir.tmLanguage.cache and /dev/null differ diff --git a/LaTeX/LaTeX.tmLanguage.cache b/LaTeX/LaTeX.tmLanguage.cache deleted file mode 100644 index 2448941..0000000 Binary files a/LaTeX/LaTeX.tmLanguage.cache and /dev/null differ diff --git a/LaTeX/TeX Math.tmLanguage.cache b/LaTeX/TeX Math.tmLanguage.cache deleted file mode 100644 index 09651af..0000000 Binary files a/LaTeX/TeX Math.tmLanguage.cache and /dev/null differ diff --git a/LaTeX/TeX.tmLanguage.cache b/LaTeX/TeX.tmLanguage.cache deleted file mode 100644 index 9ef4cd4..0000000 Binary files a/LaTeX/TeX.tmLanguage.cache and /dev/null differ diff --git a/Lisp/Comments.tmPreferences.cache b/Lisp/Comments.tmPreferences.cache deleted file mode 100644 index 2001b7f..0000000 Binary files a/Lisp/Comments.tmPreferences.cache and /dev/null differ diff --git a/Lisp/Lisp.tmLanguage.cache b/Lisp/Lisp.tmLanguage.cache deleted file mode 100644 index dff53cc..0000000 Binary files a/Lisp/Lisp.tmLanguage.cache and /dev/null differ diff --git a/Lua/Comments.tmPreferences.cache b/Lua/Comments.tmPreferences.cache deleted file mode 100644 index 7391fbd..0000000 Binary files a/Lua/Comments.tmPreferences.cache and /dev/null differ diff --git a/Lua/Indent.tmPreferences.cache b/Lua/Indent.tmPreferences.cache deleted file mode 100644 index 8fd9e32..0000000 Binary files a/Lua/Indent.tmPreferences.cache and /dev/null differ diff --git a/Lua/Lua.tmLanguage.cache b/Lua/Lua.tmLanguage.cache deleted file mode 100644 index b9cdb7f..0000000 Binary files a/Lua/Lua.tmLanguage.cache and /dev/null differ diff --git a/Makefile/Makefile.tmLanguage.cache b/Makefile/Makefile.tmLanguage.cache deleted file mode 100644 index d71a79f..0000000 Binary files a/Makefile/Makefile.tmLanguage.cache and /dev/null differ diff --git a/Makefile/Miscellaneous.tmPreferences.cache b/Makefile/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 41e4ea1..0000000 Binary files a/Makefile/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/Markdown/Indent%3A Raw.tmPreferences.cache b/Markdown/Indent%3A Raw.tmPreferences.cache deleted file mode 100644 index 47ae0c6..0000000 Binary files a/Markdown/Indent%3A Raw.tmPreferences.cache and /dev/null differ diff --git a/Markdown/Markdown.tmLanguage.cache b/Markdown/Markdown.tmLanguage.cache deleted file mode 100644 index e384d76..0000000 Binary files a/Markdown/Markdown.tmLanguage.cache and /dev/null differ diff --git a/Markdown/MultiMarkdown.tmLanguage.cache b/Markdown/MultiMarkdown.tmLanguage.cache deleted file mode 100644 index cbbe61c..0000000 Binary files a/Markdown/MultiMarkdown.tmLanguage.cache and /dev/null differ diff --git a/Markdown/Symbol List - Heading.tmPreferences.cache b/Markdown/Symbol List - Heading.tmPreferences.cache deleted file mode 100644 index 4f9c518..0000000 Binary files a/Markdown/Symbol List - Heading.tmPreferences.cache and /dev/null differ diff --git a/Matlab/Indent.tmPreferences.cache b/Matlab/Indent.tmPreferences.cache deleted file mode 100644 index d6cb677..0000000 Binary files a/Matlab/Indent.tmPreferences.cache and /dev/null differ diff --git a/Matlab/Matlab.tmLanguage.cache b/Matlab/Matlab.tmLanguage.cache deleted file mode 100644 index 2fd3fa2..0000000 Binary files a/Matlab/Matlab.tmLanguage.cache and /dev/null differ diff --git a/Matlab/Miscellaneous.tmPreferences.cache b/Matlab/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 8721b6b..0000000 Binary files a/Matlab/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/Matlab/Symbols.tmPreferences.cache b/Matlab/Symbols.tmPreferences.cache deleted file mode 100644 index 1bc5028..0000000 Binary files a/Matlab/Symbols.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Indent rules.tmPreferences.cache b/OCaml/Indent rules.tmPreferences.cache deleted file mode 100644 index 4c83e41..0000000 Binary files a/OCaml/Indent rules.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Miscellaneous.tmPreferences.cache b/OCaml/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 48e0d22..0000000 Binary files a/OCaml/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/OCaml/OCaml.tmLanguage.cache b/OCaml/OCaml.tmLanguage.cache deleted file mode 100644 index b6dc816..0000000 Binary files a/OCaml/OCaml.tmLanguage.cache and /dev/null differ diff --git a/OCaml/OCamllex.tmLanguage.cache b/OCaml/OCamllex.tmLanguage.cache deleted file mode 100644 index 231696b..0000000 Binary files a/OCaml/OCamllex.tmLanguage.cache and /dev/null differ diff --git a/OCaml/OCamlyacc.tmLanguage.cache b/OCaml/OCamlyacc.tmLanguage.cache deleted file mode 100644 index db3658d..0000000 Binary files a/OCaml/OCamlyacc.tmLanguage.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Classes.tmPreferences.cache b/OCaml/Symbol List%3A Classes.tmPreferences.cache deleted file mode 100644 index 9765886..0000000 Binary files a/OCaml/Symbol List%3A Classes.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Exceptions.tmPreferences.cache b/OCaml/Symbol List%3A Exceptions.tmPreferences.cache deleted file mode 100644 index b6c322e..0000000 Binary files a/OCaml/Symbol List%3A Exceptions.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Ocamllex pattern definition.tmPreferences.cache b/OCaml/Symbol List%3A Ocamllex pattern definition.tmPreferences.cache deleted file mode 100644 index bb289c8..0000000 Binary files a/OCaml/Symbol List%3A Ocamllex pattern definition.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Ocamllex pattern references.tmPreferences.cache b/OCaml/Symbol List%3A Ocamllex pattern references.tmPreferences.cache deleted file mode 100644 index 1c47040..0000000 Binary files a/OCaml/Symbol List%3A Ocamllex pattern references.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Ocamllex rules.tmPreferences.cache b/OCaml/Symbol List%3A Ocamllex rules.tmPreferences.cache deleted file mode 100644 index fc804da..0000000 Binary files a/OCaml/Symbol List%3A Ocamllex rules.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Ocamlyacc non-terminal definition.tmPreferences.cache b/OCaml/Symbol List%3A Ocamlyacc non-terminal definition.tmPreferences.cache deleted file mode 100644 index 73e776c..0000000 Binary files a/OCaml/Symbol List%3A Ocamlyacc non-terminal definition.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Ocamlyacc non-terminal reference.tmPreferences.cache b/OCaml/Symbol List%3A Ocamlyacc non-terminal reference.tmPreferences.cache deleted file mode 100644 index e33aca9..0000000 Binary files a/OCaml/Symbol List%3A Ocamlyacc non-terminal reference.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Ocamlyacc token definition.tmPreferences.cache b/OCaml/Symbol List%3A Ocamlyacc token definition.tmPreferences.cache deleted file mode 100644 index c229152..0000000 Binary files a/OCaml/Symbol List%3A Ocamlyacc token definition.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Ocamlyacc token reference.tmPreferences.cache b/OCaml/Symbol List%3A Ocamlyacc token reference.tmPreferences.cache deleted file mode 100644 index e0c326d..0000000 Binary files a/OCaml/Symbol List%3A Ocamlyacc token reference.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Types.tmPreferences.cache b/OCaml/Symbol List%3A Types.tmPreferences.cache deleted file mode 100644 index 68208bb..0000000 Binary files a/OCaml/Symbol List%3A Types.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List%3A Variants.tmPreferences.cache b/OCaml/Symbol List%3A Variants.tmPreferences.cache deleted file mode 100644 index 5a3bd12..0000000 Binary files a/OCaml/Symbol List%3A Variants.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Classes.tmPreferences.cache b/OCaml/Symbol List_ Classes.tmPreferences.cache deleted file mode 100644 index 9765886..0000000 Binary files a/OCaml/Symbol List_ Classes.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Exceptions.tmPreferences.cache b/OCaml/Symbol List_ Exceptions.tmPreferences.cache deleted file mode 100644 index b6c322e..0000000 Binary files a/OCaml/Symbol List_ Exceptions.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Ocamllex pattern definition.tmPreferences.cache b/OCaml/Symbol List_ Ocamllex pattern definition.tmPreferences.cache deleted file mode 100644 index bb289c8..0000000 Binary files a/OCaml/Symbol List_ Ocamllex pattern definition.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Ocamllex pattern references.tmPreferences.cache b/OCaml/Symbol List_ Ocamllex pattern references.tmPreferences.cache deleted file mode 100644 index 1c47040..0000000 Binary files a/OCaml/Symbol List_ Ocamllex pattern references.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Ocamllex rules.tmPreferences.cache b/OCaml/Symbol List_ Ocamllex rules.tmPreferences.cache deleted file mode 100644 index fc804da..0000000 Binary files a/OCaml/Symbol List_ Ocamllex rules.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Ocamlyacc non-terminal definition.tmPreferences.cache b/OCaml/Symbol List_ Ocamlyacc non-terminal definition.tmPreferences.cache deleted file mode 100644 index 73e776c..0000000 Binary files a/OCaml/Symbol List_ Ocamlyacc non-terminal definition.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Ocamlyacc non-terminal reference.tmPreferences.cache b/OCaml/Symbol List_ Ocamlyacc non-terminal reference.tmPreferences.cache deleted file mode 100644 index e33aca9..0000000 Binary files a/OCaml/Symbol List_ Ocamlyacc non-terminal reference.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Ocamlyacc token definition.tmPreferences.cache b/OCaml/Symbol List_ Ocamlyacc token definition.tmPreferences.cache deleted file mode 100644 index c229152..0000000 Binary files a/OCaml/Symbol List_ Ocamlyacc token definition.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Ocamlyacc token reference.tmPreferences.cache b/OCaml/Symbol List_ Ocamlyacc token reference.tmPreferences.cache deleted file mode 100644 index e0c326d..0000000 Binary files a/OCaml/Symbol List_ Ocamlyacc token reference.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Types.tmPreferences.cache b/OCaml/Symbol List_ Types.tmPreferences.cache deleted file mode 100644 index 68208bb..0000000 Binary files a/OCaml/Symbol List_ Types.tmPreferences.cache and /dev/null differ diff --git a/OCaml/Symbol List_ Variants.tmPreferences.cache b/OCaml/Symbol List_ Variants.tmPreferences.cache deleted file mode 100644 index 5a3bd12..0000000 Binary files a/OCaml/Symbol List_ Variants.tmPreferences.cache and /dev/null differ diff --git a/OCaml/camlp4.tmLanguage.cache b/OCaml/camlp4.tmLanguage.cache deleted file mode 100644 index ff105b3..0000000 Binary files a/OCaml/camlp4.tmLanguage.cache and /dev/null differ diff --git a/Objective-C/Objective-C++.tmLanguage.cache b/Objective-C/Objective-C++.tmLanguage.cache deleted file mode 100644 index 59a9dd7..0000000 Binary files a/Objective-C/Objective-C++.tmLanguage.cache and /dev/null differ diff --git a/Objective-C/Objective-C.tmLanguage.cache b/Objective-C/Objective-C.tmLanguage.cache deleted file mode 100644 index efdea82..0000000 Binary files a/Objective-C/Objective-C.tmLanguage.cache and /dev/null differ diff --git a/PHP/Comments.tmPreferences.cache b/PHP/Comments.tmPreferences.cache deleted file mode 100644 index c6c07b7..0000000 Binary files a/PHP/Comments.tmPreferences.cache and /dev/null differ diff --git a/PHP/Indentation Rules.tmPreferences.cache b/PHP/Indentation Rules.tmPreferences.cache deleted file mode 100644 index 6630103..0000000 Binary files a/PHP/Indentation Rules.tmPreferences.cache and /dev/null differ diff --git a/PHP/PHP.tmLanguage.cache b/PHP/PHP.tmLanguage.cache deleted file mode 100644 index e1e8214..0000000 Binary files a/PHP/PHP.tmLanguage.cache and /dev/null differ diff --git a/PHP/Symbol List.tmPreferences.cache b/PHP/Symbol List.tmPreferences.cache deleted file mode 100644 index 092762f..0000000 Binary files a/PHP/Symbol List.tmPreferences.cache and /dev/null differ diff --git a/Package Control/Default.sublime-commands b/Package Control/Default.sublime-commands index 84be427..7d823ee 100644 --- a/Package Control/Default.sublime-commands +++ b/Package Control/Default.sublime-commands @@ -4,7 +4,7 @@ "command": "add_repository" }, { - "caption": "Package Control: Add Repository Channel", + "caption": "Package Control: Add Channel", "command": "add_repository_channel" }, { diff --git a/Package Control/Package Control.py b/Package Control/Package Control.py index db838df..5994d70 100644 --- a/Package Control/Package Control.py +++ b/Package Control/Package Control.py @@ -8,7 +8,7 @@ import urllib import urllib2 import json -import fnmatch +from fnmatch import fnmatch import re import threading import datetime @@ -19,6 +19,85 @@ try: import ssl + import httplib + import socket + + class InvalidCertificateException(httplib.HTTPException, urllib2.URLError): + def __init__(self, host, cert, reason): + httplib.HTTPException.__init__(self) + self.host = host + self.cert = cert + self.reason = reason + + def __str__(self): + return ('Host %s returned an invalid certificate (%s) %s\n' % + (self.host, self.reason, self.cert)) + + class CertValidatingHTTPSConnection(httplib.HTTPConnection): + default_port = httplib.HTTPS_PORT + + def __init__(self, host, port=None, key_file=None, cert_file=None, + ca_certs=None, strict=None, **kwargs): + httplib.HTTPConnection.__init__(self, host, port, strict, **kwargs) + self.key_file = key_file + self.cert_file = cert_file + self.ca_certs = ca_certs + if self.ca_certs: + self.cert_reqs = ssl.CERT_REQUIRED + else: + self.cert_reqs = ssl.CERT_NONE + + def _GetValidHostsForCert(self, cert): + if 'subjectAltName' in cert: + return [x[1] for x in cert['subjectAltName'] + if x[0].lower() == 'dns'] + else: + return [x[0][1] for x in cert['subject'] + if x[0][0].lower() == 'commonname'] + + def _ValidateCertificateHostname(self, cert, hostname): + hosts = self._GetValidHostsForCert(cert) + for host in hosts: + host_re = host.replace('.', '\.').replace('*', '[^.]*') + if re.search('^%s$' % (host_re,), hostname, re.I): + return True + return False + + def connect(self): + sock = socket.create_connection((self.host, self.port)) + self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, + certfile=self.cert_file, + cert_reqs=self.cert_reqs, + ca_certs=self.ca_certs) + if self.cert_reqs & ssl.CERT_REQUIRED: + cert = self.sock.getpeercert() + hostname = self.host.split(':', 0)[0] + if not self._ValidateCertificateHostname(cert, hostname): + raise InvalidCertificateException(hostname, cert, + 'hostname mismatch') + + if hasattr(urllib2, 'HTTPSHandler'): + class VerifiedHTTPSHandler(urllib2.HTTPSHandler): + def __init__(self, **kwargs): + urllib2.AbstractHTTPHandler.__init__(self) + self._connection_args = kwargs + + def https_open(self, req): + def http_class_wrapper(host, **kwargs): + full_kwargs = dict(self._connection_args) + full_kwargs.update(kwargs) + return CertValidatingHTTPSConnection(host, **full_kwargs) + + try: + return self.do_open(http_class_wrapper, req) + except urllib2.URLError, e: + if type(e.reason) == ssl.SSLError and e.reason.args[0] == 1: + raise InvalidCertificateException(req.host, '', + e.reason.args[1]) + raise + + https_request = urllib2.HTTPSHandler.do_request_ + except (ImportError): pass @@ -74,8 +153,8 @@ def fetch_channel(self): try: channel_info = json.loads(channel_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' channel ' + self.channel + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'channel %s.') % (__name__, self.channel)) channel_info = False self.channel_info = channel_info @@ -98,6 +177,12 @@ def get_repositories(self): return False return self.channel_info['repositories'] + def get_certs(self): + self.fetch_channel() + if self.channel_info == False: + return False + return self.channel_info.get('certs', {}) + def get_packages(self, repo): self.fetch_channel() if self.channel_info == False: @@ -151,8 +236,8 @@ def fetch_repo(self): try: self.repo_info = json.loads(repository_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' repository ' + self.repo + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'repository %s.') % (__name__, self.repo)) self.repo_info = False def get_packages(self): @@ -219,8 +304,8 @@ def get_packages(self): try: repo_info = json.loads(repo_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' repository ' + api_url + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'repository %s.') % (__name__, api_url)) return False commit_api_url = api_url + '/commits?' + \ @@ -234,8 +319,8 @@ def get_packages(self): try: commit_info = json.loads(commit_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' repository ' + commit_api_url + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'repository %s.') % (__name__, commit_api_url)) return False download_url = 'https://nodeload.github.com/' + \ @@ -254,7 +339,8 @@ def get_packages(self): package = { 'name': repo_info['name'], - 'description': repo_info['description'], + 'description': repo_info['description'] if \ + repo_info['description'] else 'No description provided', 'url': homepage, 'author': repo_info['owner']['login'], 'last_modified': timestamp.strftime('%Y-%m-%d %H:%M:%S'), @@ -294,8 +380,8 @@ def get_packages(self): try: repo_info = json.loads(repo_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' repository ' + api_url + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'repository %s.') % (__name__, api_url)) return False packages = {} @@ -311,8 +397,8 @@ def get_packages(self): try: commit_info = json.loads(commit_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' repository ' + commit_api_url + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'repository %s.') % (__name__, commit_api_url)) return False commit_date = commit_info[0]['commit']['committer']['date'] @@ -327,7 +413,8 @@ def get_packages(self): package = { 'name': package_info['name'], - 'description': package_info['description'], + 'description': repo_info['description'] if \ + repo_info['description'] else 'No description provided', 'url': homepage, 'author': package_info['owner']['login'], 'last_modified': timestamp.strftime('%Y-%m-%d %H:%M:%S'), @@ -367,8 +454,8 @@ def get_packages(self): try: repo_info = json.loads(repo_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' repository ' + api_url + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'repository %s.') % (__name__, api_url)) return False changeset_url = api_url + '/changesets/default' @@ -379,8 +466,8 @@ def get_packages(self): try: last_commit = json.loads(changeset_json) except (ValueError): - sublime.error_message(__name__ + ': Error parsing JSON from ' + - ' repository ' + changeset_url + '.') + sublime.error_message(('%s: Error parsing JSON from ' + + 'repository %s.') % (__name__, changeset_url)) return False commit_date = last_commit['timestamp'] timestamp = datetime.datetime.strptime(commit_date[0:19], @@ -392,8 +479,9 @@ def get_packages(self): if not homepage: homepage = self.repo package = { - 'name': repo_info['slug'], - 'description': repo_info['description'], + 'name': repo_info['name'], + 'description': repo_info['description'] if \ + repo_info['description'] else 'No description provided', 'url': homepage, 'author': repo_info['owner'], 'last_modified': timestamp.strftime('%Y-%m-%d %H:%M:%S'), @@ -427,20 +515,42 @@ def __str__(self): return repr(self.returncode) -class CliDownloader(): +class Downloader(): + def check_certs(self, domain, timeout): + cert_info = self.settings.get('certs', {}).get( + domain) + if not cert_info: + print '%s: No CA certs available for %s.' % (__name__, + domain) + return False + cert_path = os.path.join(sublime.packages_path(), 'Package Control', + 'certs', cert_info[0]) + ca_bundle_path = os.path.join(sublime.packages_path(), + 'Package Control', 'certs', 'ca-bundle.crt') + if not os.path.exists(cert_path): + cert_downloader = self.__class__(self.settings) + cert_contents = cert_downloader.download(cert_info[1], + 'Error downloading CA certs for %s.' % (domain), timeout, 1) + if not cert_contents: + return False + with open(cert_path, 'wb') as f: + f.write(cert_contents) + with open(ca_bundle_path, 'ab') as f: + f.write("\n" + cert_contents) + return ca_bundle_path + + +class CliDownloader(Downloader): def __init__(self, settings): self.settings = settings def find_binary(self, name): - dirs = ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin', '/usr/bin', - '/sbin', '/bin'] - for dir in dirs: + for dir in os.environ['PATH'].split(os.pathsep): path = os.path.join(dir, name) if os.path.exists(path): return path - raise BinaryNotFoundError('The binary ' + name + ' could not be ' + - 'located') + raise BinaryNotFoundError('The binary %s could not be located' % name) def execute(self, args): proc = subprocess.Popen(args, stdin=subprocess.PIPE, @@ -455,7 +565,7 @@ def execute(self, args): return output -class UrlLib2Downloader(): +class UrlLib2Downloader(Downloader): def __init__(self, settings): self.settings = settings @@ -473,7 +583,16 @@ def download(self, url, error_message, timeout, tries): proxy_handler = urllib2.ProxyHandler(proxies) else: proxy_handler = urllib2.ProxyHandler() - urllib2.install_opener(urllib2.build_opener(proxy_handler)) + handlers = [proxy_handler] + + secure_url_match = re.match('^https://([^/]+)', url) + if secure_url_match != None: + secure_domain = secure_url_match.group(1) + bundle_path = self.check_certs(secure_domain, timeout) + if not bundle_path: + return False + handlers.append(VerifiedHTTPSHandler(ca_certs=bundle_path)) + urllib2.install_opener(urllib2.build_opener(*handlers)) while tries > 0: tries -= 1 @@ -486,17 +605,18 @@ def download(self, url, error_message, timeout, tries): except (urllib2.HTTPError) as (e): # Bitbucket and Github ratelimit using 503 a decent amount if str(e.code) == '503': - print (__name__ + ': Downloading %s was rate limited, ' + - 'trying again') % url + print ('%s: Downloading %s was rate limited, ' + + 'trying again') % (__name__, url) continue print '%s: %s HTTP error %s downloading %s.' % (__name__, error_message, str(e.code), url) + except (urllib2.URLError) as (e): # Bitbucket and Github timeout a decent amount if str(e.reason) == 'The read operation timed out' or \ str(e.reason) == 'timed out': - print (__name__ + ': Downloading %s timed out, trying ' + - 'again') % url + print ('%s: Downloading %s timed out, trying ' + + 'again') % (__name__, url) continue print '%s: %s URL error %s downloading %s.' % (__name__, error_message, str(e.reason), url) @@ -518,7 +638,17 @@ def download(self, url, error_message, timeout, tries): self.tmp_file = tempfile.NamedTemporaryFile().name command = [self.wget, '--connect-timeout=' + str(int(timeout)), '-o', - self.tmp_file, '-O', '-', '-U', 'Sublime Package Control', url] + self.tmp_file, '-O', '-', '-U', 'Sublime Package Control'] + + secure_url_match = re.match('^https://([^/]+)', url) + if secure_url_match != None: + secure_domain = secure_url_match.group(1) + bundle_path = self.check_certs(secure_domain, timeout) + if not bundle_path: + return False + command.append(u'--ca-certificate=' + bundle_path) + + command.append(url) if self.settings.get('http_proxy'): os.putenv('http_proxy', self.settings.get('http_proxy')) @@ -527,7 +657,7 @@ def download(self, url, error_message, timeout, tries): if self.settings.get('https_proxy'): os.putenv('https_proxy', self.settings.get('https_proxy')) - while tries > 1: + while tries > 0: tries -= 1 try: result = self.execute(command) @@ -545,8 +675,8 @@ def download(self, url, error_message, timeout, tries): regex = re.compile('^.*ERROR (\d+):.*', re.S) if re.sub(regex, '\\1', error_line) == '503': # GitHub and BitBucket seem to rate limit via 503 - print (__name__ + ': Downloading %s was rate limited' + - ', trying again') % url + print ('%s: Downloading %s was rate limited' + + ', trying again') % (__name__, url) continue error_string = 'HTTP error ' + re.sub('^.*? ERROR ', '', error_line) @@ -555,8 +685,8 @@ def download(self, url, error_message, timeout, tries): error_string = re.sub('^.*?failed: ', '', error_line) # GitHub and BitBucket seem to time out a lot if error_string.find('timed out') != -1: - print (__name__ + ': Downloading %s timed out, ' + - 'trying again') % url + print ('%s: Downloading %s timed out, ' + + 'trying again') % (__name__, url) continue else: @@ -580,7 +710,17 @@ def download(self, url, error_message, timeout, tries): if not self.curl: return False command = [self.curl, '-f', '--user-agent', 'Sublime Package Control', - '--connect-timeout', str(int(timeout)), '-sS', url] + '--connect-timeout', str(int(timeout)), '-sS'] + + secure_url_match = re.match('^https://([^/]+)', url) + if secure_url_match != None: + secure_domain = secure_url_match.group(1) + bundle_path = self.check_certs(secure_domain, timeout) + if not bundle_path: + return False + command.extend(['--cacert', bundle_path]) + + command.append(url) if self.settings.get('http_proxy'): os.putenv('http_proxy', self.settings.get('http_proxy')) @@ -589,7 +729,7 @@ def download(self, url, error_message, timeout, tries): if self.settings.get('https_proxy'): os.putenv('HTTPS_PROXY', self.settings.get('https_proxy')) - while tries > 1: + while tries > 0: tries -= 1 try: return self.execute(command) @@ -598,19 +738,19 @@ def download(self, url, error_message, timeout, tries): code = re.sub('^.*?(\d+)\s*$', '\\1', e.output) if code == '503': # GitHub and BitBucket seem to rate limit via 503 - print (__name__ + ': Downloading %s was rate limited' + - ', trying again') % url + print ('%s: Downloading %s was rate limited' + + ', trying again') % (__name__, url) continue error_string = 'HTTP error ' + code elif e.returncode == 6: error_string = 'URL error host not found' elif e.returncode == 28: # GitHub and BitBucket seem to time out a lot - print (__name__ + ': Downloading %s timed out, trying ' + - 'again') % url + print ('%s: Downloading %s timed out, trying ' + + 'again') % (__name__, url) continue else: - error_string = e.output + error_string = e.output.rstrip() print '%s: %s %s downloading %s.' % (__name__, error_message, error_string, url) @@ -673,6 +813,15 @@ def find_binary(self, name): if self.binary: return self.binary + # Try the path first + for dir in os.environ['PATH'].split(os.pathsep): + path = os.path.join(dir, name) + if os.path.exists(path): + return path + + # This is left in for backwards compatibility and for windows + # users who may have the binary, albeit in a common dir that may + # not be part of the PATH if os.name == 'nt': dirs = ['C:\\Program Files\\Git\\bin', 'C:\\Program Files (x86)\\Git\\bin', @@ -683,9 +832,7 @@ def find_binary(self, name): 'C:\\Program Files\\TortoiseHg', 'C:\\cygwin\\bin'] else: - dirs = ['/usr/local/git/bin', '/usr/local/sbin', - '/usr/local/bin', '/usr/sbin', - '/usr/bin', '/sbin', '/bin'] + dirs = ['/usr/local/git/bin'] for dir in dirs: path = os.path.join(dir, name) @@ -816,7 +963,9 @@ def __init__(self): 'git_binary', 'git_update_command', 'hg_binary', 'hg_update_command', 'http_proxy', 'https_proxy', 'auto_upgrade_ignore', 'auto_upgrade_frequency', - 'submit_usage', 'submit_url', 'renamed_packages']: + 'submit_usage', 'submit_url', 'renamed_packages', + 'files_to_include', 'files_to_include_binary', 'certs', + 'ignore_vcs_packages']: if settings.get(setting) == None: continue self.settings[setting] = settings.get(setting) @@ -834,7 +983,7 @@ def normalize(v): return cmp(normalize(version1), normalize(version2)) def download_url(self, url, error_message): - has_ssl = 'ssl' in sys.modules + has_ssl = 'ssl' in sys.modules and hasattr(urllib2, 'HTTPSHandler') is_ssl = re.search('^https://', url) != None if (is_ssl and has_ssl) or not is_ssl: @@ -848,9 +997,9 @@ def download_url(self, url, error_message): pass if not downloader: - sublime.error_message(__name__ + ': Unable to download ' + - url + ' due to no ssl module available and no capable ' + - 'program found. Please install curl or wget.') + sublime.error_message(('%s: Unable to download %s due to no ' + + 'ssl module available and no capable program found. Please ' + + 'install curl or wget.') % (__name__, url)) return False timeout = self.settings.get('timeout', 3) @@ -899,6 +1048,13 @@ def list_repositories(self): {})) self.settings['renamed_packages'] = renamed_packages + certs_cache_key = channel + '.certs' + certs_cache = _channel_repository_cache.get(certs_cache_key) + if certs_cache and certs_cache.get('time') > time.time(): + certs = self.settings.get('certs', {}) + certs.update(certs_cache.get('data')) + self.settings['certs'] = certs + if channel_repositories == None or \ self.settings.get('package_name_map') == None or \ self.settings.get('renamed_packages') == None: @@ -948,6 +1104,16 @@ def list_repositories(self): 'renamed_packages', {}) self.settings['renamed_packages'].update(renamed_packages) + certs = provider.get_certs() + _channel_repository_cache[certs_cache_key] = { + 'time': time.time() + self.settings.get('cache_length', + 300), + 'data': certs + } + if certs: + self.settings['certs'] = self.settings.get('certs', {}) + self.settings['certs'].update(certs) + repositories.extend(channel_repositories) return repositories @@ -1069,9 +1235,9 @@ def create_package(self, package_name, package_destination, package_dir = self.get_package_dir(package_name) + '/' if not os.path.exists(package_dir): - sublime.error_message(__name__ + ': The folder for the ' + - 'package name specified, %s, does not exist in %s' % - (package_name, sublime.packages_path())) + sublime.error_message(('%s: The folder for the package name ' + + 'specified, %s, does not exist in %s') % + (__name__, package_name, sublime.packages_path())) return False package_filename = package_name + '.sublime-package' @@ -1088,16 +1254,18 @@ def create_package(self, package_name, package_destination, package_file = zipfile.ZipFile(package_path, "w", compression=zipfile.ZIP_DEFLATED) except (OSError, IOError) as (exception): - sublime.error_message(__name__ + ': An error occurred ' + - 'creating the package file %s in %s. %s' % (package_filename, + sublime.error_message(('%s: An error occurred creating the ' + + 'package file %s in %s. %s') % (__name__, package_filename, package_destination, str(exception))) return False dirs_to_ignore = self.settings.get('dirs_to_ignore', []) if not binary_package: files_to_ignore = self.settings.get('files_to_ignore', []) + files_to_include = self.settings.get('files_to_include', []) else: files_to_ignore = self.settings.get('files_to_ignore_binary', []) + files_to_include = self.settings.get('files_to_include_binary', []) package_dir_regex = re.compile('^' + re.escape(package_dir)) for root, dirs, files in os.walk(package_dir): @@ -1105,19 +1273,18 @@ def create_package(self, package_name, package_destination, paths = dirs paths.extend(files) for path in paths: - if any(fnmatch.fnmatch(path, pattern) for pattern in - files_to_ignore): - continue full_path = os.path.join(root, path) relative_path = re.sub(package_dir_regex, '', full_path) + + ignore_matches = [fnmatch(relative_path, p) for p in files_to_ignore] + include_matches = [fnmatch(relative_path, p) for p in files_to_include] + if any(ignore_matches) and not any(include_matches): + continue + if os.path.isdir(full_path): continue package_file.write(full_path, relative_path) - init_script = os.path.join(package_dir, '__init__.py') - if binary_package and os.path.exists(init_script): - package_file.write(init_script, re.sub(package_dir_regex, '', - init_script)) package_file.close() return True @@ -1126,8 +1293,8 @@ def install_package(self, package_name): packages = self.list_available_packages() if package_name not in packages.keys(): - sublime.error_message(__name__ + ': The package specified,' + - ' %s, is not available.' % (package_name,)) + sublime.error_message(('%s: The package specified, %s, is ' + + 'not available.') % (__name__, package_name)) return False download = packages[package_name]['downloads'][0] @@ -1146,10 +1313,20 @@ def install_package(self, package_name): 'package-metadata.json') if os.path.exists(os.path.join(package_dir, '.git')): + if self.settings.get('ignore_vcs_packages'): + sublime.error_message(('%s: Skipping git package %s since ' + + 'the setting ignore_vcs_packages is set to true') % + (__name__, package_name)) + return False return GitUpgrader(self.settings['git_binary'], self.settings['git_update_command'], package_dir, self.settings['cache_length']).run() elif os.path.exists(os.path.join(package_dir, '.hg')): + if self.settings.get('ignore_vcs_packages'): + sublime.error_message(('%s: Skipping hg package %s since ' + + 'the setting ignore_vcs_packages is set to true') % + (__name__, package_name)) + return False return HgUpgrader(self.settings['hg_binary'], self.settings['hg_update_command'], package_dir, self.settings['cache_length']).run() @@ -1179,23 +1356,30 @@ def install_package(self, package_name): package_backup_dir = os.path.join(backup_dir, package_name) shutil.copytree(package_dir, package_backup_dir) except (OSError, IOError) as (exception): - sublime.error_message(__name__ + ': An error occurred while' + - ' trying to backup the package directory for %s. %s' % - (package_name, str(exception))) + sublime.error_message(('%s: An error occurred while trying ' + + 'to backup the package directory for %s. %s') % + (__name__, package_name, str(exception))) shutil.rmtree(package_backup_dir) return False - package_zip = zipfile.ZipFile(package_path, 'r') + try: + package_zip = zipfile.ZipFile(package_path, 'r') + except (zipfile.BadZipfile): + sublime.error_message(('%s: An error occurred while ' + + 'trying to unzip the package file for %s. Please try ' + + 'installing the package again.') % (__name__, package_name)) + return False + root_level_paths = [] last_path = None for path in package_zip.namelist(): last_path = path if path.find('/') in [len(path) - 1, -1]: root_level_paths.append(path) - if path[0] == '/' or path.find('..') != -1: - sublime.error_message(__name__ + ': The package ' + - 'specified, %s, contains files outside of the package ' + - 'dir and cannot be safely installed.' % (package_name,)) + if path[0] == '/' or path.find('../') != -1 or path.find('..\\') != -1: + sublime.error_message(('%s: The package specified, %s, ' + + 'contains files outside of the package dir and cannot ' + + 'be safely installed.') % (__name__, package_name)) return False if last_path and len(root_level_paths) == 0: @@ -1218,9 +1402,8 @@ def install_package(self, package_name): if os.name == 'nt': regex = ':|\*|\?|"|<|>|\|' if re.search(regex, dest) != None: - print ('%s: Skipping file from package ' + - 'named %s due to an invalid filename') % (__name__, - path) + print ('%s: Skipping file from package named %s due to ' + + 'an invalid filename') % (__name__, path) continue # If there was only a single directory in the package, we remove @@ -1255,9 +1438,8 @@ def add_extracted_dirs(dir): try: open(dest, 'wb').write(package_zip.read(path)) except (IOError, UnicodeDecodeError): - print ('%s: Skipping file from package ' + - 'named %s due to an invalid filename') % (__name__, - path) + print ('%s: Skipping file from package named %s due to ' + + 'an invalid filename') % (__name__, path) package_zip.close() # Here we clean out any files that were not just overwritten @@ -1405,8 +1587,8 @@ def remove_package(self, package_name): installed_packages = self.list_packages() if package_name not in installed_packages: - sublime.error_message(__name__ + ': The package specified,' + - ' %s, is not installed.' % (package_name,)) + sublime.error_message(('%s: The package specified, %s, is not ' + + 'installed.') % (__name__, package_name)) return False os.chdir(sublime.packages_path()) @@ -1429,27 +1611,27 @@ def remove_package(self, package_name): if os.path.exists(package_path): os.remove(package_path) except (OSError, IOError) as (exception): - sublime.error_message(__name__ + ': An error occurred while' + - ' trying to remove the package file for %s. %s' % - (package_name, str(exception))) + sublime.error_message(('%s: An error occurred while trying to ' + + 'remove the package file for %s. %s') % (__name__, + package_name, str(exception))) return False try: if os.path.exists(installed_package_path): os.remove(installed_package_path) except (OSError, IOError) as (exception): - sublime.error_message(__name__ + ': An error occurred while' + - ' trying to remove the installed package file for %s. %s' % - (package_name, str(exception))) + sublime.error_message(('%s: An error occurred while trying to ' + + 'remove the installed package file for %s. %s') % (__name__, + package_name, str(exception))) return False try: if os.path.exists(pristine_package_path): os.remove(pristine_package_path) except (OSError, IOError) as (exception): - sublime.error_message(__name__ + ': An error occurred while' + - ' trying to remove the pristine package file for %s. %s' % - (package_name, str(exception))) + sublime.error_message(('%s: An error occurred while trying to ' + + 'remove the pristine package file for %s. %s') % (__name__, + package_name, str(exception))) return False # We don't delete the actual package dir immediately due to a bug @@ -1478,13 +1660,13 @@ def remove_package(self, package_name): # Remove the package from the installed packages list def clear_package(): - settings = sublime.load_settings(__name__ + '.sublime-settings') + settings = sublime.load_settings('%s.sublime-settings' % __name__) installed_packages = settings.get('installed_packages', []) if not installed_packages: installed_packages = [] installed_packages.remove(package_name) settings.set('installed_packages', installed_packages) - sublime.save_settings(__name__ + '.sublime-settings') + sublime.save_settings('%s.sublime-settings' % __name__) sublime.set_timeout(clear_package, 1) if can_delete_dir: @@ -1500,14 +1682,18 @@ def record_usage(self, params): params['sublime_platform'] = self.settings.get('platform') params['sublime_version'] = self.settings.get('version') url = self.settings.get('submit_url') + '?' + urllib.urlencode(params) + result = self.download_url(url, 'Error submitting usage information.') + if result == False: + return + try: result = json.loads(result) if result['result'] != 'success': raise ValueError() except (ValueError): - print '%s: Error submitting usage information for %s' % \ - (__name__, params['package']) + print '%s: Error submitting usage information for %s' % (__name__, + params['package']) class PackageCreator(): @@ -1515,8 +1701,8 @@ def show_panel(self): self.manager = PackageManager() self.packages = self.manager.list_packages() if not self.packages: - sublime.error_message(__name__ + ': There are no packages ' + - 'available to be packaged.') + sublime.error_message(('%s: There are no packages available to ' + + 'be packaged.') % (__name__)) return self.window.show_quick_panel(self.packages, self.on_done) @@ -1526,8 +1712,7 @@ def get_package_destination(self): # We check destination via an if statement instead of using # the dict.get() method since the key may be set, but to a blank value if not destination: - destination = os.path.join(os.path.expanduser('~'), - 'Desktop') + destination = os.path.join(os.path.expanduser('~'), 'Desktop') return destination @@ -1607,12 +1792,16 @@ def make_package_list(self, ignore_actions=[], override_action=None, else: if os.path.exists(os.path.join(sublime.packages_path(), package, '.git')): + if settings.get('ignore_vcs_packages'): + continue vcs = 'git' incoming = GitUpgrader(settings.get('git_binary'), settings.get('git_update_command'), package_dir, settings.get('cache_length')).incoming() elif os.path.exists(os.path.join(sublime.packages_path(), package, '.hg')): + if settings.get('ignore_vcs_packages'): + continue vcs = 'hg' incoming = HgUpgrader(settings.get('hg_binary'), settings.get('hg_update_command'), package_dir, @@ -1653,8 +1842,10 @@ def make_package_list(self, ignore_actions=[], override_action=None, if action in ignore_actions: continue - package_entry.append(info.get('description', 'No description ' + - 'provided')) + description = info.get('description') + if not description: + description = 'No description provided' + package_entry.append(description) package_entry.append(action + extra + ' ' + re.sub('^https?://', '', info['url'])) package_list.append(package_entry) @@ -1700,8 +1891,8 @@ def run(self): def show_quick_panel(): if not self.package_list: - sublime.error_message(__name__ + ': There are no packages ' + - 'available for installation.') + sublime.error_message(('%s: There are no packages ' + + 'available for installation.') % __name__) return self.window.show_quick_panel(self.package_list, self.on_done) sublime.set_timeout(show_quick_panel, 10) @@ -1733,8 +1924,8 @@ def run(self): def show_quick_panel(): if not self.package_list: - sublime.error_message(__name__ + ': There are no packages ' + - 'ready for upgrade.') + sublime.error_message(('%s: There are no packages ' + + 'ready for upgrade.') % __name__) return self.window.show_quick_panel(self.package_list, self.on_done) sublime.set_timeout(show_quick_panel, 10) @@ -1787,8 +1978,10 @@ def make_package_list(self, action=''): metadata = self.manager.get_metadata(package) package_dir = os.path.join(sublime.packages_path(), package) - package_entry.append(metadata.get('description', - 'No description provided')) + description = metadata.get('description') + if not description: + description = 'No description provided' + package_entry.append(description) version = metadata.get('version') if not version and os.path.exists(os.path.join(package_dir, @@ -1829,8 +2022,8 @@ def run(self): def show_quick_panel(): if not self.package_list: - sublime.error_message(__name__ + ': There are no packages ' + - 'to list.') + sublime.error_message(('%s: There are no packages ' + + 'to list.') % __name__) return self.window.show_quick_panel(self.package_list, self.on_done) sublime.set_timeout(show_quick_panel, 10) @@ -1855,8 +2048,8 @@ def __init__(self, window): def run(self): self.package_list = self.make_package_list('remove') if not self.package_list: - sublime.error_message(__name__ + ': There are no packages ' + - 'that can be removed.') + sublime.error_message(('%s: There are no packages ' + + 'that can be removed.') % __name__) return self.window.show_quick_panel(self.package_list, self.on_done) @@ -1900,19 +2093,19 @@ def unignore_package(): class AddRepositoryChannelCommand(sublime_plugin.WindowCommand): def run(self): - self.window.show_input_panel('Repository Channel JSON URL', '', + self.window.show_input_panel('Channel JSON URL', '', self.on_done, self.on_change, self.on_cancel) def on_done(self, input): - settings = sublime.load_settings(__name__ + '.sublime-settings') + settings = sublime.load_settings('%s.sublime-settings' % __name__) repository_channels = settings.get('repository_channels', []) if not repository_channels: repository_channels = [] repository_channels.append(input) settings.set('repository_channels', repository_channels) - sublime.save_settings(__name__ + '.sublime-settings') - sublime.status_message('Repository channel ' + input + - ' successfully added') + sublime.save_settings('%s.sublime-settings' % __name__) + sublime.status_message(('Channel %s successfully ' + + 'added') % input) def on_change(self, input): pass @@ -1928,14 +2121,14 @@ def run(self): self.on_change, self.on_cancel) def on_done(self, input): - settings = sublime.load_settings(__name__ + '.sublime-settings') + settings = sublime.load_settings('%s.sublime-settings' % __name__) repositories = settings.get('repositories', []) if not repositories: repositories = [] repositories.append(input) settings.set('repositories', repositories) - sublime.save_settings(__name__ + '.sublime-settings') - sublime.status_message('Repository ' + input + ' successfully added') + sublime.save_settings('%s.sublime-settings' % __name__) + sublime.status_message('Repository %s successfully added' % input) def on_change(self, input): pass @@ -1955,8 +2148,8 @@ def run(self): self.package_list = list(set(packages) - set(disabled_packages)) self.package_list.sort() if not self.package_list: - sublime.error_message(__name__ + ': There are no enabled ' + - 'packages to disable.') + sublime.error_message(('%s: There are no enabled packages' + + 'to disable.') % __name__) return self.window.show_quick_panel(self.package_list, self.on_done) @@ -1970,9 +2163,9 @@ def on_done(self, picked): ignored_packages.append(package) self.settings.set('ignored_packages', ignored_packages) sublime.save_settings('Global.sublime-settings') - sublime.status_message('Package ' + package + ' successfully added ' + - 'to list of disabled packages - restarting Sublime Text may be ' - 'required') + sublime.status_message(('Package %s successfully added to list of ' + + 'disabled packages - restarting Sublime Text may be required') % + package) class EnablePackageCommand(sublime_plugin.WindowCommand): @@ -1981,8 +2174,8 @@ def run(self): self.disabled_packages = self.settings.get('ignored_packages') self.disabled_packages.sort() if not self.disabled_packages: - sublime.error_message(__name__ + ': There are no disabled ' + - 'packages to enable.') + sublime.error_message(('%s: There are no disabled packages ' + + 'to enable.') % __name__) return self.window.show_quick_panel(self.disabled_packages, self.on_done) @@ -1994,9 +2187,9 @@ def on_done(self, picked): self.settings.set('ignored_packages', list(set(ignored) - set([package]))) sublime.save_settings('Global.sublime-settings') - sublime.status_message('Package ' + package + ' successfully removed' + - ' from list of disabled packages - restarting Sublime Text may be ' - 'required') + sublime.status_message(('Package %s successfully removed from list ' + + 'of disabled packages - restarting Sublime Text may be required') % + package) class PackageStartup(): @@ -2159,11 +2352,18 @@ def run(self): metadata_path = os.path.join(package_dir, 'package-metadata.json') # Cleanup packages that could not be removed due to in-use files - if os.path.exists(os.path.join(package_dir, - 'package-control.cleanup')): - shutil.rmtree(package_dir) - print '%s: Removed old directory for package %s' % \ - (__name__, package_name) + cleanup_file = os.path.join(package_dir, 'package-control.cleanup') + if os.path.exists(cleanup_file): + try: + shutil.rmtree(package_dir) + print '%s: Removed old directory for package %s' % \ + (__name__, package_name) + except (OSError) as (e): + if not os.path.exists(cleanup_file): + open(cleanup_file, 'w').close() + print ('%s: Unable to remove old directory for package ' + + '%s - deferring until next start: %s') % (__name__, + package_name, str(e)) # This adds previously installed packages from old versions of PC if os.path.exists(metadata_path) and \ diff --git a/Package Control/Package Control.pyc b/Package Control/Package Control.pyc deleted file mode 100644 index 6173636..0000000 Binary files a/Package Control/Package Control.pyc and /dev/null differ diff --git a/Package Control/Package Control.sublime-settings b/Package Control/Package Control.sublime-settings index 2ab981c..b2b03b5 100644 --- a/Package Control/Package Control.sublime-settings +++ b/Package Control/Package Control.sublime-settings @@ -3,7 +3,7 @@ // The repositories from these channels are placed in order after the // repositories from the "repositories" setting "repository_channels": [ - "http://sublime.wbond.net/repositories.json" + "https://sublime.wbond.net/repositories.json" ], // A list of URLs that contain a packages JSON file. These repositories @@ -11,6 +11,10 @@ // setting "repositories": [], + "certs": { + "sublime.wbond.net": ["7f4f8622b4fd001c7f648e09aae7edaa", ""] + }, + // This helps solve naming issues where a repository it not named the // same as the package should be. This is primarily only useful for // GitHub and BitBucket repositories. This mapping will override the @@ -22,7 +26,7 @@ "submit_usage": true, // The URL to post install, upgrade and removal notices to - "submit_url": "http://sublime.wbond.net/submit", + "submit_url": "https://sublime.wbond.net/submit", // If packages should be automatically upgraded when ST2 starts "auto_upgrade": true, @@ -46,12 +50,18 @@ // http_proxy is, http_proxy will be used for https_proxy also "https_proxy": "", + // Setting this to true will cause Package Control to ignore all git + // and hg repositories - this may help if trying to list packages to install + // hangs + "ignore_vcs_packages": false, + // Custom paths to VCS binaries for when they can't be automatically // found on the system and a package includes a VCS metadata directory "git_binary": "", - "git_update_command": ["pull", "origin", "master"], + "git_update_command": ["pull", "origin", "master", "--ff", "--commit"], "hg_binary": "", + // Be sure to keep the remote name as the last argument "hg_update_command": ["pull", "--update", "default"], @@ -59,11 +69,16 @@ "dirs_to_ignore": [ ".hg", ".git", ".svn", "_darcs", "CVS" ], + // Files to ignore when creating a package "files_to_ignore": [ ".hgignore", ".gitignore", ".bzrignore", "*.pyc", "*.sublime-project", "*.sublime-workspace", "*.tmTheme.cache" ], + + // Files to include, even if they match a pattern in files_to_ignore + "files_to_include": [], + // Files to ignore when creating a binary package. By default binary // packages ship with .pyc files instead of .py files. If an __init__.py // file exists, it will always be included, even if it matches one of @@ -72,6 +87,13 @@ ".hgignore", ".gitignore", ".bzrignore", "*.py", "*.sublime-project", "*.sublime-workspace", "*.tmTheme.cache" ], + + // Files to include for a binary package, even if they match a pattern i + // files_to_ignore_binary + "files_to_include_binary": [ + "__init__.py" + ], + // When a package is created, copy it to this folder - defaults to Desktop "package_destination": "" } \ No newline at end of file diff --git a/Package Control/package-metadata.json b/Package Control/package-metadata.json index 913cf6f..c634a81 100644 --- a/Package Control/package-metadata.json +++ b/Package Control/package-metadata.json @@ -1 +1 @@ -{"url": "http://wbond.net/sublime_packages/package_control", "version": "1.4.1", "description": "A full-featured package manager"} \ No newline at end of file +{"url": "http://wbond.net/sublime_packages/package_control", "version": "1.5.0", "description": "A full-featured package manager"} \ No newline at end of file diff --git a/Perl/Miscellaneous.tmPreferences.cache b/Perl/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 49130fa..0000000 Binary files a/Perl/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/Perl/Perl.tmLanguage.cache b/Perl/Perl.tmLanguage.cache deleted file mode 100644 index fbf392e..0000000 Binary files a/Perl/Perl.tmLanguage.cache and /dev/null differ diff --git a/Python/Miscellaneous.tmPreferences.cache b/Python/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 541d0c0..0000000 Binary files a/Python/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/Python/Python.tmLanguage.cache b/Python/Python.tmLanguage.cache deleted file mode 100644 index a031d89..0000000 Binary files a/Python/Python.tmLanguage.cache and /dev/null differ diff --git a/Python/Regular Expressions (Python).tmLanguage.cache b/Python/Regular Expressions (Python).tmLanguage.cache deleted file mode 100644 index d726e15..0000000 Binary files a/Python/Regular Expressions (Python).tmLanguage.cache and /dev/null differ diff --git a/Python/Symbol List Hide Decorator.tmPreferences.cache b/Python/Symbol List Hide Decorator.tmPreferences.cache deleted file mode 100644 index a7d95c1..0000000 Binary files a/Python/Symbol List Hide Decorator.tmPreferences.cache and /dev/null differ diff --git a/Python/Symbol List.tmPreferences.cache b/Python/Symbol List.tmPreferences.cache deleted file mode 100644 index 28f7a23..0000000 Binary files a/Python/Symbol List.tmPreferences.cache and /dev/null differ diff --git a/R/Comments.tmPreferences.cache b/R/Comments.tmPreferences.cache deleted file mode 100644 index 210f5e9..0000000 Binary files a/R/Comments.tmPreferences.cache and /dev/null differ diff --git a/R/Methods.tmPreferences.cache b/R/Methods.tmPreferences.cache deleted file mode 100644 index c2962d5..0000000 Binary files a/R/Methods.tmPreferences.cache and /dev/null differ diff --git a/R/R Console.tmLanguage.cache b/R/R Console.tmLanguage.cache deleted file mode 100644 index b615906..0000000 Binary files a/R/R Console.tmLanguage.cache and /dev/null differ diff --git a/R/R.tmLanguage.cache b/R/R.tmLanguage.cache deleted file mode 100644 index 5d780d4..0000000 Binary files a/R/R.tmLanguage.cache and /dev/null differ diff --git a/R/Rd (R Documentation).tmLanguage.cache b/R/Rd (R Documentation).tmLanguage.cache deleted file mode 100644 index 30ec45c..0000000 Binary files a/R/Rd (R Documentation).tmLanguage.cache and /dev/null differ diff --git a/R/Symbol List (Rd Documentation).tmPreferences.cache b/R/Symbol List (Rd Documentation).tmPreferences.cache deleted file mode 100644 index a869817..0000000 Binary files a/R/Symbol List (Rd Documentation).tmPreferences.cache and /dev/null differ diff --git a/Rails/HTML (Rails).tmLanguage.cache b/Rails/HTML (Rails).tmLanguage.cache deleted file mode 100644 index fa4f9ac..0000000 Binary files a/Rails/HTML (Rails).tmLanguage.cache and /dev/null differ diff --git a/Rails/JavaScript (Rails).tmLanguage.cache b/Rails/JavaScript (Rails).tmLanguage.cache deleted file mode 100644 index 18d5e56..0000000 Binary files a/Rails/JavaScript (Rails).tmLanguage.cache and /dev/null differ diff --git a/Rails/Ruby Haml Comments.tmPreferences.cache b/Rails/Ruby Haml Comments.tmPreferences.cache deleted file mode 100644 index c403ff3..0000000 Binary files a/Rails/Ruby Haml Comments.tmPreferences.cache and /dev/null differ diff --git a/Rails/Ruby Haml.tmLanguage.cache b/Rails/Ruby Haml.tmLanguage.cache deleted file mode 100644 index a6b3c6b..0000000 Binary files a/Rails/Ruby Haml.tmLanguage.cache and /dev/null differ diff --git a/Rails/Ruby on Rails.tmLanguage.cache b/Rails/Ruby on Rails.tmLanguage.cache deleted file mode 100644 index 3503a00..0000000 Binary files a/Rails/Ruby on Rails.tmLanguage.cache and /dev/null differ diff --git a/Rails/SQL (Rails).tmLanguage.cache b/Rails/SQL (Rails).tmLanguage.cache deleted file mode 100644 index 7f0875b..0000000 Binary files a/Rails/SQL (Rails).tmLanguage.cache and /dev/null differ diff --git a/Rails/Template (ERB).tmPreferences.cache b/Rails/Template (ERB).tmPreferences.cache deleted file mode 100644 index c42b69b..0000000 Binary files a/Rails/Template (ERB).tmPreferences.cache and /dev/null differ diff --git a/Rails/Template (Haml).tmPreferences.cache b/Rails/Template (Haml).tmPreferences.cache deleted file mode 100644 index d4b9c25..0000000 Binary files a/Rails/Template (Haml).tmPreferences.cache and /dev/null differ diff --git a/Regular Expressions/RegExp.tmLanguage.cache b/Regular Expressions/RegExp.tmLanguage.cache deleted file mode 100644 index db4c219..0000000 Binary files a/Regular Expressions/RegExp.tmLanguage.cache and /dev/null differ diff --git a/RestructuredText/Comments.tmPreferences.cache b/RestructuredText/Comments.tmPreferences.cache deleted file mode 100644 index fa0237d..0000000 Binary files a/RestructuredText/Comments.tmPreferences.cache and /dev/null differ diff --git a/RestructuredText/reStructuredText.tmLanguage.cache b/RestructuredText/reStructuredText.tmLanguage.cache deleted file mode 100644 index 098776d..0000000 Binary files a/RestructuredText/reStructuredText.tmLanguage.cache and /dev/null differ diff --git a/Ruby/Comments.tmPreferences.cache b/Ruby/Comments.tmPreferences.cache deleted file mode 100644 index 56e48ee..0000000 Binary files a/Ruby/Comments.tmPreferences.cache and /dev/null differ diff --git a/Ruby/Miscellaneous.tmPreferences.cache b/Ruby/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 8f62265..0000000 Binary files a/Ruby/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/Ruby/Ruby.tmLanguage.cache b/Ruby/Ruby.tmLanguage.cache deleted file mode 100644 index f085572..0000000 Binary files a/Ruby/Ruby.tmLanguage.cache and /dev/null differ diff --git a/Ruby/Symbo List%3A Method.tmPreferences.cache b/Ruby/Symbo List%3A Method.tmPreferences.cache deleted file mode 100644 index 7dd28d0..0000000 Binary files a/Ruby/Symbo List%3A Method.tmPreferences.cache and /dev/null differ diff --git a/Ruby/Symbol List%3A No Function Call.tmPreferences.cache b/Ruby/Symbol List%3A No Function Call.tmPreferences.cache deleted file mode 100644 index 21f23d4..0000000 Binary files a/Ruby/Symbol List%3A No Function Call.tmPreferences.cache and /dev/null differ diff --git a/SQL/Comments.tmPreferences.cache b/SQL/Comments.tmPreferences.cache deleted file mode 100644 index 0ab57c2..0000000 Binary files a/SQL/Comments.tmPreferences.cache and /dev/null differ diff --git a/SQL/Miscellaneous.tmPreferences.cache b/SQL/Miscellaneous.tmPreferences.cache deleted file mode 100644 index ebbd08d..0000000 Binary files a/SQL/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/SQL/SQL.tmLanguage.cache b/SQL/SQL.tmLanguage.cache deleted file mode 100644 index 08e2bda..0000000 Binary files a/SQL/SQL.tmLanguage.cache and /dev/null differ diff --git a/Scala/Comments.tmPreferences.cache b/Scala/Comments.tmPreferences.cache deleted file mode 100644 index 60c16d5..0000000 Binary files a/Scala/Comments.tmPreferences.cache and /dev/null differ diff --git a/Scala/Scala.tmLanguage.cache b/Scala/Scala.tmLanguage.cache deleted file mode 100644 index a81bc4e..0000000 Binary files a/Scala/Scala.tmLanguage.cache and /dev/null differ diff --git a/Scala/Symbols.tmPreferences.cache b/Scala/Symbols.tmPreferences.cache deleted file mode 100644 index 361b069..0000000 Binary files a/Scala/Symbols.tmPreferences.cache and /dev/null differ diff --git a/ShellScript/Comments.tmPreferences.cache b/ShellScript/Comments.tmPreferences.cache deleted file mode 100644 index 3aa2083..0000000 Binary files a/ShellScript/Comments.tmPreferences.cache and /dev/null differ diff --git a/ShellScript/Miscellaneous.tmPreferences.cache b/ShellScript/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 042d277..0000000 Binary files a/ShellScript/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/ShellScript/Shell-Unix-Generic.tmLanguage.cache b/ShellScript/Shell-Unix-Generic.tmLanguage.cache deleted file mode 100644 index 5d7647e..0000000 Binary files a/ShellScript/Shell-Unix-Generic.tmLanguage.cache and /dev/null differ diff --git a/TCL/Comments.tmPreferences.cache b/TCL/Comments.tmPreferences.cache deleted file mode 100644 index 033b075..0000000 Binary files a/TCL/Comments.tmPreferences.cache and /dev/null differ diff --git a/TCL/HTML (Tcl).tmLanguage.cache b/TCL/HTML (Tcl).tmLanguage.cache deleted file mode 100644 index bdd29f8..0000000 Binary files a/TCL/HTML (Tcl).tmLanguage.cache and /dev/null differ diff --git a/TCL/Tcl.tmLanguage.cache b/TCL/Tcl.tmLanguage.cache deleted file mode 100644 index 6cde8ed..0000000 Binary files a/TCL/Tcl.tmLanguage.cache and /dev/null differ diff --git a/Text/Plain text.tmLanguage.cache b/Text/Plain text.tmLanguage.cache deleted file mode 100644 index 0375276..0000000 Binary files a/Text/Plain text.tmLanguage.cache and /dev/null differ diff --git a/Textile/Textile.tmLanguage.cache b/Textile/Textile.tmLanguage.cache deleted file mode 100644 index 52f4474..0000000 Binary files a/Textile/Textile.tmLanguage.cache and /dev/null differ diff --git a/Theme - Default/Widgets.stTheme.cache b/Theme - Default/Widgets.stTheme.cache deleted file mode 100644 index 63d1f4a..0000000 Binary files a/Theme - Default/Widgets.stTheme.cache and /dev/null differ diff --git a/Theme - Soda/README.md b/Theme - Soda/README.md index eba7775..1bd12dd 100644 --- a/Theme - Soda/README.md +++ b/Theme - Soda/README.md @@ -4,16 +4,20 @@ Dark and light custom UI themes for Sublime Text 2. ## Design -![Soda Light Theme](http://buymeasoda.github.com/soda-theme/images/screenshots/soda-light-theme.png?v=6) +![Soda Light Theme](http://buymeasoda.github.com/soda-theme/images/screenshots/soda-light-theme.png?v=7) -![Soda Dark Theme](http://buymeasoda.github.com/soda-theme/images/screenshots/soda-dark-theme.png?v=6) +![Soda Dark Theme](http://buymeasoda.github.com/soda-theme/images/screenshots/soda-dark-theme.png?v=7) ## Installation -If you are a git user, the best way to install the theme and keep up to date is to clone the repo directly into your `Packages` directory in the Sublime Text 2 application settings area. +### Using Sublime Package Control + +If you are using Will Bond's excellent [Sublime Package Control](http://wbond.net/sublime_packages/package_control), you can easily install Soda Theme via the `Package Control: Install Package` menu item. The Soda Theme package is listed as `Theme - Soda` in the packages list. ### Using Git +Alternatively, if you are a git user, you can install the theme and keep up to date by cloning the repo directly into your `Packages` directory in the Sublime Text 2 application settings area. + Go to your Sublime Text 2 `Packages` directory and clone the theme repository using the command below: git clone https://github.com/buymeasoda/soda-theme/ "Theme - Soda" @@ -28,10 +32,10 @@ Go to your Sublime Text 2 `Packages` directory and clone the theme repository us To configure Sublime Text 2 to use the theme: -* Open your Sublime Text 2 User Global Preferences file `Sublime Text 2 -> Preferences -> Global Settings - User` +* Open your User Settings Preferences file `Sublime Text 2 -> Preferences -> Settings - User` * Add (or update) your theme entry to be `"theme": "Soda Light.sublime-theme"` or `"theme": "Soda Dark.sublime-theme"` -### Example User Global Settings +### Example User Settings { "theme": "Soda Light.sublime-theme" diff --git a/Theme - Soda/Soda Dark.sublime-theme b/Theme - Soda/Soda Dark.sublime-theme index e4d316f..3dfda26 100644 --- a/Theme - Soda/Soda Dark.sublime-theme +++ b/Theme - Soda/Soda Dark.sublime-theme @@ -47,13 +47,6 @@ "settings": ["show_tab_close_buttons"], "content_margin": [22, 6, 15, 4] }, - { - // Tab dirty state - "class": "tab_control", - "settings": ["highlight_modified_tabs"], - "attributes": ["dirty"], - "content_margin": [22, 6, 15, 4] - }, { // Hover tab state "class": "tab_control", @@ -70,23 +63,21 @@ }, // Tab labels { - // Inactive tab label "class": "tab_label", "fade": true, - "fg": [204, 204, 204], - "bg": [66, 66, 66] + "fg": [175, 175, 175], + "shadow_color": [0, 0, 0], + "shadow_offset": [0, -1] }, { - // Inactive tab label hover "class": "tab_label", "parents": [{"class": "tab_control", "attributes": ["hover"]}], - "bg": [75, 75, 75] + "fg": [200, 200, 200] }, { - // Active tab label "class": "tab_label", "parents": [{"class": "tab_control", "attributes": ["selected"]}], - "bg": [78, 78, 78] + "fg": [245, 245, 245] }, // Tab close button { @@ -107,7 +98,7 @@ "content_margin": [8, 8] }, { - // Tab close hover action + // Tab close button hover "class": "tab_close_button", "attributes": ["hover"], "layer0.opacity": 0.0, @@ -116,29 +107,33 @@ // Tab dirty button { "class": "tab_close_button", - "settings": ["highlight_modified_tabs"], "parents": [{"class": "tab_control", "attributes": ["dirty"]}], - "content_margin": [8, 8], "layer0.texture": "Theme - Soda/Soda Dark/tab-dirty.png", - "layer0.opacity": 1.0, + "layer0.opacity": 1.0, "layer1.opacity": 0.0 }, { // Tab dirty button hover "class": "tab_close_button", - "settings": ["highlight_modified_tabs"], "parents": [{"class": "tab_control", "attributes": ["dirty"]}], "attributes": ["hover"], "layer0.opacity": 0.0, "layer1.opacity": 1.0 }, + // Tab close button hidden with highlight modified flag true + { + // Tab dirty state (close button hidden) + "class": "tab_control", + "settings": ["!show_tab_close_buttons", "highlight_modified_tabs"], + "attributes": ["dirty"], + "content_margin": [22, 6, 15, 4] + }, { - // Tab dirty button hover (close button hidden) + // Tab dirty button (close button hidden) "class": "tab_close_button", - "settings": ["highlight_modified_tabs"], - "settings": ["!show_tab_close_buttons"], + "settings": ["!show_tab_close_buttons", "highlight_modified_tabs"], "parents": [{"class": "tab_control", "attributes": ["dirty"]}], - "attributes": ["hover"], + "content_margin": [8, 8], "layer0.opacity": 1.0, "layer1.opacity": 0.0 }, @@ -168,7 +163,7 @@ "attributes": ["pressed"], "layer0.opacity": 0.0, "layer1.opacity": 1.0 - }, + }, { "class": "fold_button_control", "attributes": ["expanded"], @@ -300,6 +295,16 @@ "layer0.opacity": 1.0 }, +// +// GRID LAYOUT +// + + { + "class": "grid_layout_control", + "border_size": 1, + "border_color": [70, 70, 70] + }, + // // MINI MAP // @@ -422,17 +427,32 @@ "shadow_color": [0, 0, 0], "shadow_offset": [0, 1] }, - { - "class": "sidebar_heading", - "parents": [{"class": "tree_row", "attributes": ["selected"]}], - "color": [210, 210, 210] - }, // Sidebar entry { "class": "sidebar_label", "color": [125, 125, 125], "shadow_offset": [0, 0] }, + // Sidebar folder entry + { + "class": "sidebar_label", + "parents": [{"class": "tree_row", "attributes": ["expandable"]}], + "color": [210, 210, 210], + "shadow_color": [0, 0, 0], + "shadow_offset": [0, 1] + }, + { + "class": "sidebar_label", + "parents": [{"class": "tree_row", "attributes": ["expandable", "hover"]}], + "color": [235, 235, 235] + }, + { + "class": "sidebar_label", + "parents": [{"class": "tree_row", "attributes": ["expandable"]}], + "settings": ["bold_folder_labels"], + "font.bold": true + }, + // Sidebar entry selected { "class": "sidebar_label", "parents": [{"class": "tree_row", "attributes": ["selected"]}], @@ -441,7 +461,7 @@ "shadow_offset": [0, 1] }, // Sidebar file close - { + { "class": "close_button", "layer0.texture": "Theme - Soda/Soda Dark/file-close.png", "layer0.opacity": 0.0, @@ -610,27 +630,27 @@ }, { "class": "quick_panel_label", - "fg": [190, 190, 190, 255], - "match_fg": [255, 255, 255, 255], + "fg": [210, 210, 210, 255], + "match_fg": [126, 199, 239, 255], "bg": [41, 41, 41, 255], - "selected_fg": [200, 200, 200, 255], - "selected_match_fg": [255, 255, 255, 255], + "selected_fg": [255, 255, 255, 255], + "selected_match_fg": [166, 229, 255, 255], "selected_bg": [24, 24, 24, 255] }, { "class": "quick_panel_path_label", - "fg": [120, 120, 120, 255], - "match_fg": [200, 200, 200, 255], + "fg": [130, 130, 130, 255], + "match_fg": [220, 220, 220, 255], "bg": [41, 41, 41, 255], - "selected_fg": [130, 130, 130, 255], - "selected_match_fg": [255, 255, 255, 255], + "selected_fg": [175, 175, 175, 255], + "selected_match_fg": [220, 220, 220, 255], "selected_bg": [24, 24, 24, 255] }, { "class": "quick_panel_score_label", - "fg": [137, 208, 244, 255], + "fg": [126, 199, 239, 255], "bg": [41, 41, 41, 255], - "selected_fg": [137, 208, 244, 255], + "selected_fg": [166, 229, 255, 255], "selected_bg": [24, 24, 24, 255] }, @@ -865,4 +885,4 @@ "layer0.texture": "Theme - Soda/Soda Dark/icon-highlight-on.png" } -] \ No newline at end of file +] diff --git a/Theme - Soda/Soda Light.sublime-theme b/Theme - Soda/Soda Light.sublime-theme index c7b6461..57ef803 100644 --- a/Theme - Soda/Soda Light.sublime-theme +++ b/Theme - Soda/Soda Light.sublime-theme @@ -46,13 +46,6 @@ "class": "tab_control", "settings": ["show_tab_close_buttons"], "content_margin": [22, 6, 15, 4] - }, - { - // Tab dirty state - "class": "tab_control", - "settings": ["highlight_modified_tabs"], - "attributes": ["dirty"], - "content_margin": [22, 6, 15, 4] }, { // Hover tab state @@ -70,23 +63,22 @@ }, // Tab labels { - // Inactive tab label "class": "tab_label", "fade": true, - "fg": [0, 0, 0], - "bg": [222, 222, 222] + "fg": [50, 50, 50], + "shadow_color": [235, 235, 235], + "shadow_offset": [0, 1] }, { - // Inactive tab label hover "class": "tab_label", "parents": [{"class": "tab_control", "attributes": ["hover"]}], - "bg": [234, 234, 234] + "fg": [25, 25, 25] }, { - // Active tab label "class": "tab_label", "parents": [{"class": "tab_control", "attributes": ["selected"]}], - "bg": [242, 242, 242] + "fg": [0, 0, 0], + "shadow_color": [255, 255, 255] }, // Tab close button { @@ -112,33 +104,37 @@ "attributes": ["hover"], "layer0.opacity": 0.0, "layer1.opacity": 1.0 - }, + }, // Tab dirty button { "class": "tab_close_button", - "settings": ["highlight_modified_tabs"], "parents": [{"class": "tab_control", "attributes": ["dirty"]}], - "content_margin": [8, 8], "layer0.texture": "Theme - Soda/Soda Light/tab-dirty.png", - "layer0.opacity": 1.0, + "layer0.opacity": 1.0, "layer1.opacity": 0.0 }, { // Tab dirty button hover "class": "tab_close_button", - "settings": ["highlight_modified_tabs"], "parents": [{"class": "tab_control", "attributes": ["dirty"]}], "attributes": ["hover"], "layer0.opacity": 0.0, "layer1.opacity": 1.0 }, + // Tab close button hidden with highlight modified flag true { - // Tab dirty button hover (close button hidden) + // Tab dirty state (close button hidden) + "class": "tab_control", + "settings": ["!show_tab_close_buttons", "highlight_modified_tabs"], + "attributes": ["dirty"], + "content_margin": [22, 6, 15, 4] + }, + { + // Tab dirty button (close button hidden) "class": "tab_close_button", - "settings": ["highlight_modified_tabs"], - "settings": ["!show_tab_close_buttons"], + "settings": ["!show_tab_close_buttons", "highlight_modified_tabs"], "parents": [{"class": "tab_control", "attributes": ["dirty"]}], - "attributes": ["hover"], + "content_margin": [8, 8], "layer0.opacity": 1.0, "layer1.opacity": 0.0 }, @@ -168,7 +164,7 @@ "attributes": ["pressed"], "layer0.opacity": 0.0, "layer1.opacity": 1.0 - }, + }, { "class": "fold_button_control", "attributes": ["expanded"], @@ -300,6 +296,16 @@ "layer0.opacity": 1.0 }, +// +// GRID LAYOUT +// + + { + "class": "grid_layout_control", + "border_size": 1, + "border_color": [165, 165, 165] + }, + // // MINI MAP // @@ -419,18 +425,39 @@ "shadow_color": [241, 244, 247], "shadow_offset": [0, 1] }, - { - "class": "sidebar_heading", - "parents": [{"class": "tree_row", "attributes": ["selected"]}], - "color": [255, 255, 255], - "shadow_color": [34, 94, 145] - }, // Sidebar entry { "class": "sidebar_label", "color": [0, 0, 0], "shadow_offset": [0, 0] }, + // Sidebar folder entry + { + "class": "sidebar_label", + "parents": [{"class": "tree_row", "attributes": ["expandable"]}], + "color": [90, 103, 115], + "shadow_color": [241, 244, 247], + "shadow_offset": [0, 1] + }, + { + "class": "sidebar_label", + "parents": [{"class": "tree_row", "attributes": ["expandable", "hover"]}], + "color": [70, 80, 89] + }, + { + "class": "sidebar_label", + "parents": [{"class": "tree_row", "attributes": ["expandable"]}], + "settings": ["bold_folder_labels"], + "color": [110, 126, 141], + "font.bold": true + }, + { + "class": "sidebar_label", + "parents": [{"class": "tree_row", "attributes": ["expandable", "hover"]}], + "settings": ["bold_folder_labels"], + "color": [90, 103, 115] + }, + // Sidebar entry selected { "class": "sidebar_label", "parents": [{"class": "tree_row", "attributes": ["selected"]}], @@ -474,7 +501,7 @@ "parents": [{"class": "tree_row", "attributes": ["selected"]}], "layer0.texture": "Theme - Soda/Soda Light/file-dirty-selected.png" }, - { + { "class": "close_button", "attributes": ["dirty"], "parents": [{"class": "tree_row", "attributes": ["hover"]}], @@ -861,4 +888,4 @@ "layer0.texture": "Theme - Soda/Soda Light/icon-highlight-on.png" } -] \ No newline at end of file +] diff --git a/Theme - Soda/package-metadata.json b/Theme - Soda/package-metadata.json index 1bf5f4b..220dd67 100644 --- a/Theme - Soda/package-metadata.json +++ b/Theme - Soda/package-metadata.json @@ -1 +1 @@ -{"url": "https://github.com/buymeasoda/soda-theme", "version": "2012.01.03.04.52.34", "description": "Dark and light custom UI themes for Sublime Text 2"} \ No newline at end of file +{"url": "https://github.com/buymeasoda/soda-theme", "version": "2012.05.27.04.57.17", "description": "Dark and light custom UI themes for Sublime Text 2"} \ No newline at end of file diff --git a/User/Base File.sublime-settings b/User/Base File.sublime-settings index 596b2df..2812a9d 100644 --- a/User/Base File.sublime-settings +++ b/User/Base File.sublime-settings @@ -3,7 +3,6 @@ "default_line_ending": "unix", "draw_minimap_border": true, "draw_white_space": "all", - "font_face": "Consolas", "font_size": 10, "highlight_line": true, "tab_size": 4, diff --git a/User/Package Control.sublime-settings b/User/Package Control.sublime-settings index b935afa..a9063bf 100644 --- a/User/Package Control.sublime-settings +++ b/User/Package Control.sublime-settings @@ -1,10 +1,12 @@ { - "auto_upgrade_last_run": 1326371975, + "auto_upgrade_last_run": 1338932338, "installed_packages": [ "Alignment", + "Drupal Project Autocomplete", + "Drupal Snippets", "Package Control", - "SFTP", + "SublimeCodeIntel", "sublimelint", "Theme - Soda", "ZenCoding" diff --git a/User/tidy_json.pyc b/User/tidy_json.pyc deleted file mode 100644 index d6a0a2e..0000000 Binary files a/User/tidy_json.pyc and /dev/null differ diff --git a/User/tidy_xml.pyc b/User/tidy_xml.pyc deleted file mode 100644 index e465994..0000000 Binary files a/User/tidy_xml.pyc and /dev/null differ diff --git a/Vintage/vintage.pyc b/Vintage/vintage.pyc deleted file mode 100644 index 82d1acc..0000000 Binary files a/Vintage/vintage.pyc and /dev/null differ diff --git a/Vintage/vintage_commands.pyc b/Vintage/vintage_commands.pyc deleted file mode 100644 index 27e0806..0000000 Binary files a/Vintage/vintage_commands.pyc and /dev/null differ diff --git a/Vintage/vintage_motions.pyc b/Vintage/vintage_motions.pyc deleted file mode 100644 index 3a48ca3..0000000 Binary files a/Vintage/vintage_motions.pyc and /dev/null differ diff --git a/XML/Comments.tmPreferences.cache b/XML/Comments.tmPreferences.cache deleted file mode 100644 index 4f7313e..0000000 Binary files a/XML/Comments.tmPreferences.cache and /dev/null differ diff --git a/XML/Miscellaneous.tmPreferences.cache b/XML/Miscellaneous.tmPreferences.cache deleted file mode 100644 index 9332d97..0000000 Binary files a/XML/Miscellaneous.tmPreferences.cache and /dev/null differ diff --git a/XML/Symbol List%3A Templates.tmPreferences.cache b/XML/Symbol List%3A Templates.tmPreferences.cache deleted file mode 100644 index a4dea2e..0000000 Binary files a/XML/Symbol List%3A Templates.tmPreferences.cache and /dev/null differ diff --git a/XML/XML.tmLanguage.cache b/XML/XML.tmLanguage.cache deleted file mode 100644 index 9982260..0000000 Binary files a/XML/XML.tmLanguage.cache and /dev/null differ diff --git a/XML/XSL.tmLanguage.cache b/XML/XSL.tmLanguage.cache deleted file mode 100644 index 2b406f2..0000000 Binary files a/XML/XSL.tmLanguage.cache and /dev/null differ diff --git a/YAML/Comments.tmPreferences.cache b/YAML/Comments.tmPreferences.cache deleted file mode 100644 index 2b65d80..0000000 Binary files a/YAML/Comments.tmPreferences.cache and /dev/null differ diff --git a/YAML/YAML.tmLanguage.cache b/YAML/YAML.tmLanguage.cache deleted file mode 100644 index 224cd90..0000000 Binary files a/YAML/YAML.tmLanguage.cache and /dev/null differ diff --git a/ZenCoding/.hg_archival.txt b/ZenCoding/.hg_archival.txt index 65713af..015e258 100644 --- a/ZenCoding/.hg_archival.txt +++ b/ZenCoding/.hg_archival.txt @@ -1,5 +1,5 @@ repo: 168bd3100b8042c4e5341abe810d24441053d44c -node: 495292bf418eefb5f24572475715146d7ea843c3 +node: 8be235edaf1caa1d25c2cd5509f274f1e25815d3 branch: default latesttag: null -latesttagdistance: 79 +latesttagdistance: 98 diff --git a/ZenCoding/Default (Linux).sublime-keymap b/ZenCoding/Default (Linux).sublime-keymap index e9cc56a..83e21d1 100644 --- a/ZenCoding/Default (Linux).sublime-keymap +++ b/ZenCoding/Default (Linux).sublime-keymap @@ -676,18 +676,5 @@ "match_all": true, "key": "following_text" }] - }, - { - "keys" : ["tab"], - "__doc__" : "Insert a completion when there is a snippet active as long as there's a valid abbrevation that doesn't end in a full stop.", - "command" : "insert_best_completion", - "args" : {"exact" : false, "default": "\t"}, - "context": [ - { "key": "is_zen", "operator": "equal", "operand": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\.$", "match_all": true }, - { "key": "has_next_field", "operator": "equal", "operand": true }, - { "key": "setting.tab_completion", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html", "match_all": true} - ] - } - ] \ No newline at end of file + } +] \ No newline at end of file diff --git a/ZenCoding/Default (OSX).sublime-keymap b/ZenCoding/Default (OSX).sublime-keymap index e9cc56a..83e21d1 100644 --- a/ZenCoding/Default (OSX).sublime-keymap +++ b/ZenCoding/Default (OSX).sublime-keymap @@ -676,18 +676,5 @@ "match_all": true, "key": "following_text" }] - }, - { - "keys" : ["tab"], - "__doc__" : "Insert a completion when there is a snippet active as long as there's a valid abbrevation that doesn't end in a full stop.", - "command" : "insert_best_completion", - "args" : {"exact" : false, "default": "\t"}, - "context": [ - { "key": "is_zen", "operator": "equal", "operand": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\.$", "match_all": true }, - { "key": "has_next_field", "operator": "equal", "operand": true }, - { "key": "setting.tab_completion", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html", "match_all": true} - ] - } - ] \ No newline at end of file + } +] \ No newline at end of file diff --git a/ZenCoding/Default (Windows).sublime-keymap b/ZenCoding/Default (Windows).sublime-keymap index e9cc56a..1200eea 100644 --- a/ZenCoding/Default (Windows).sublime-keymap +++ b/ZenCoding/Default (Windows).sublime-keymap @@ -215,7 +215,7 @@ }, { "keys": [ - "ctrl+alt+n" + "ctrl+alt+m" ], "__doc__": "Moves caret to matching opening or closing tag\n", "args": { @@ -417,7 +417,7 @@ }, { "keys": [ - "ctrl+alt+shift+v" + "ctrl+alt+shift+f10" ], "__doc__": "Reflect CSS value: takes rule's value under caret and pastes it for the same \nrules with vendor prefixes\n@param editor: ZenEditor", "args": { @@ -676,18 +676,5 @@ "match_all": true, "key": "following_text" }] - }, - { - "keys" : ["tab"], - "__doc__" : "Insert a completion when there is a snippet active as long as there's a valid abbrevation that doesn't end in a full stop.", - "command" : "insert_best_completion", - "args" : {"exact" : false, "default": "\t"}, - "context": [ - { "key": "is_zen", "operator": "equal", "operand": true }, - { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\.$", "match_all": true }, - { "key": "has_next_field", "operator": "equal", "operand": true }, - { "key": "setting.tab_completion", "operator": "equal", "operand": true }, - { "key": "selector", "operator": "equal", "operand": "text.html", "match_all": true} - ] - } - ] \ No newline at end of file + } +] \ No newline at end of file diff --git a/ZenCoding/dynamicsnippets.py b/ZenCoding/dynamicsnippets.py index 7ac67c6..570f8a1 100644 --- a/ZenCoding/dynamicsnippets.py +++ b/ZenCoding/dynamicsnippets.py @@ -49,7 +49,7 @@ def run(self, edit, **args): self.erase = False panel = self.view.window().show_input_panel ( - self.input_message, self.default_input, None, self.insert, self.undo ) + self.input_message, self.default_input, None, self.insert, self.undo ) panel.sel().clear() panel.sel().add(sublime.Region(0, panel.size())) diff --git a/ZenCoding/dynamicsnippets.pyc b/ZenCoding/dynamicsnippets.pyc deleted file mode 100644 index e4b11e7..0000000 Binary files a/ZenCoding/dynamicsnippets.pyc and /dev/null differ diff --git a/ZenCoding/package-metadata.json b/ZenCoding/package-metadata.json index c54fb41..2c71bad 100644 --- a/ZenCoding/package-metadata.json +++ b/ZenCoding/package-metadata.json @@ -1 +1 @@ -{"url": "https://bitbucket.org/sublimator/sublime-2-zencoding", "version": "2011.09.12.02.53.56", "description": "Zen Coding support for Sublime Text 2"} \ No newline at end of file +{"url": "https://bitbucket.org/sublimator/sublime-2-zencoding", "version": "2012.01.31.12.13.28", "description": "Zen Coding support for Sublime Text 2"} \ No newline at end of file diff --git a/ZenCoding/sublimezen.py b/ZenCoding/sublimezen.py index 3ae6d46..ba307a5 100644 --- a/ZenCoding/sublimezen.py +++ b/ZenCoding/sublimezen.py @@ -135,8 +135,9 @@ def find_css_property(view, start_pt): def find_css_selector(view, start_pt): conds = [track_scope(CSS_SELECTOR)] - - if not view.match_selector(start_pt, CSS_SELECTOR): + + if not sublime.score_selector(view.scope_name(start_pt), CSS_SELECTOR): + # if not view.score_selector((start_pt), CSS_SELECTOR): conds.insert(0, track_scope(CSS_SELECTOR, False)) selector = back_track(view, start_pt, *conds)[-1] diff --git a/ZenCoding/sublimezen.pyc b/ZenCoding/sublimezen.pyc deleted file mode 100644 index 4c70699..0000000 Binary files a/ZenCoding/sublimezen.pyc and /dev/null differ diff --git a/ZenCoding/sublimezenplugin.py b/ZenCoding/sublimezenplugin.py index b4ec8c0..4d7c394 100644 --- a/ZenCoding/sublimezenplugin.py +++ b/ZenCoding/sublimezenplugin.py @@ -3,6 +3,9 @@ # Std Libs import operator +import os + +from os.path import join, dirname # Sublime Libs import sublime @@ -42,7 +45,7 @@ HTML_NOT_INSIDE_TAG = 'text.html - meta.tag' -CSS = 'source.css, source.scss' +CSS = 'source.css, source.scss, source.stylus' CSS_PROPERTY = 'meta.property-list.css - meta.property-value.css' CSS_SELECTOR = 'meta.selector.css, source.css - meta, source.scss - meta' @@ -69,7 +72,6 @@ zen_settings = sublime.load_settings('zen-coding.sublime-settings') - OPMAP = { sublime.OP_EQUAL : operator.eq, sublime.OP_NOT_EQUAL : operator.ne, @@ -123,23 +125,37 @@ def load_settings(force_reload=False): zen_settings.add_on_change('zen_coding', lambda: load_settings(force_reload=1)) +################################### ARBITRAGE ################################## + +try: + arbited +except NameError: + arbited = True + if zen_settings.get('zenarbitrage'): + from zenarbitrage import doop + doop() + ######################## REMOVE HTML/HTML_COMPLETIONS.PY ####################### def remove_html_completions(): - try: - import html_completions - hc = html_completions.HtmlCompletions - except (ImportError, AttributeError): - debug('Unable to find `html_completions.HtmlCompletions`') - return + import sublime_plugin - completions = sublime_plugin.all_callbacks['on_query_completions'] - for i, instance in enumerate (completions): - if isinstance(instance, hc): - debug('on_query_completion: removing: %s' % hc) - del completions[i] + for completer in "TagCompletions", "HtmlCompletions": + try: + import html_completions + cm = getattr(html_completions, completer) + except (ImportError, AttributeError): + debug('Unable to find `html_completions.HtmlCompletions`') + continue + + completions = sublime_plugin.all_callbacks['on_query_completions'] + for i, instance in enumerate (completions): + if isinstance(instance, cm): + debug('on_query_completion: removing: %s' % cm) + del completions[i] - debug('on_query_completion: callbacks: %r' % completions) + # The funky loader + if debug: debug('on_query_completion: callbacks: %r' % completions) sublime.set_timeout(remove_html_completions, 2000) @@ -246,6 +262,14 @@ def css_selectors(self, view, prefix, pos): return [ ( prefix, (':' + p), p.replace('|', '$1') ) for p in CSS_PSEUDO_CLASSES if not prefix or p.startswith(prefix[0].lower() ) ] + elif selector.startswith('.'): + return [] + # return [] + return [(selector, v, v) for v in + set(map(view.substr, [ + r for r in view.find_by_selector('source.css ' + 'meta.selector.css entity.other.attribute-name.class.css') + if not r.contains(pos)] ))] else: return elements @@ -258,24 +282,25 @@ def css_property_values(self, view, prefix, pos): if values and prefix and prefix in values: oq_debug("zcprop:val prop: %r values: %r" % (prop, values)) - return [(prefix, v, v) for d,v in sorted(values.items())] + return [(d, '%s\t(%s)' % (v, d), v) for d,v in sorted(values.items())] else: # Look for values relating to that property # Remove exact matches, so a \t is inserted values = [v for v in CSS_PROP_VALUES.get(prop, []) if v != prefix] if values: debug("zenmeta:val prop: %r values: %r" % (prop, values)) - return [(prefix, ':' + v, v) for v in values] + return [(v, v, v) for v in values] + # return [(v, '%s\t(%s)' % (v, v), v) for v in values] def html_elements_attributes(self, view, prefix, pos): tag = find_tag_name(view, pos) values = HTML_ELEMENTS_ATTRIBUTES.get(tag, []) - return [(prefix, '@' + v, '%s="$1"' % v) for v in values] + return [(v, '%s\t@%s' % (v,v), '%s="$1"' % v) for v in values] def html_attributes_values(self, view, prefix, pos): attr = find_attribute_name(view, pos) values = HTML_ATTRIBUTES_VALUES.get(attr, []) - return [(prefix, '@=' + v, v) for v in values] + return [(v, '%s\t@=%s' % (v,v), v) for v in values] def on_query_completions(self, view, prefix, locations): if ( not self.correct_syntax(view) or @@ -292,46 +317,52 @@ def on_query_completions(self, view, prefix, locations): # A mapping of scopes, sub scopes and handlers, first matching of which # is used. COMPLETIONS = ( - - (CSS, ( (CSS_SELECTOR, self.css_selectors), - (CSS_VALUE, self.css_property_values) )), - - (HTML, ( (HTML_INSIDE_TAG, self.html_elements_attributes), - (HTML_INSIDE_TAG_ATTRIBUTE, self.html_attributes_values) )) - ) + (CSS_SELECTOR, self.css_selectors), + (CSS_VALUE, self.css_property_values), + (HTML_INSIDE_TAG, self.html_elements_attributes), + (HTML_INSIDE_TAG_ATTRIBUTE, self.html_attributes_values) ) pos = view.sel()[0].b # Try to find some more specific contextual abbreviation - for root_selector, sub_selectors in COMPLETIONS: - for sub_selector, handler in sub_selectors: - h_name = handler.__name__ - if h_name in black_list: continue - if view.match_selector(pos, sub_selector): - - c = h_name, prefix - oq_debug('handler: %r prefix: %r' % c) - oq_debug('pos: %r scope: %r' % (pos, view.syntax_name(pos))) - - completions = handler(view, prefix, pos) - oq_debug('completions: %r' % completions) - if completions: return completions - - # Expand Zen expressions such as `d:n+m:a` or `div*5` - try: - abbr = zencoding.actions.basic.find_abbreviation(editor) - oq_debug('abbr: %r' % abbr) - - if abbr: - result = expand_abbr(abbr) - oq_debug('expand_abbr abbr: %r result: %r' % (abbr, result)) - - if result: - return [ - (abbr, abbr, result)] - - except ZenInvalidAbbreviation: - pass + for sub_selector, handler in COMPLETIONS: + h_name = handler.__name__ + if h_name in black_list: continue + if view.match_selector(pos, sub_selector): + + c = h_name, prefix + oq_debug('handler: %r prefix: %r' % c) + oq_debug('pos: %r scope: %r' % (pos, view.syntax_name(pos))) + + completions = handler(view, prefix, pos) + oq_debug('completions: %r' % completions) + if completions: return completions + + do_zen_expansion = True + html_scope_for_zen = ("text.html meta.tag " + "-meta.scope.between-tag-pair.html " + "-punctuation.definition.tag.begin.html") + + if view.match_selector(pos, 'text.html'): + if view.match_selector(pos, html_scope_for_zen): + do_zen_expansion = False + + if do_zen_expansion: + # Expand Zen expressions such as `d:n+m:a` or `div*5` + try: + + abbr = zencoding.actions.basic.find_abbreviation(editor) + oq_debug('abbr: %r' % abbr) + if abbr and not view.match_selector( locations[0], + HTML_INSIDE_TAG ): + result = expand_abbr(abbr) + oq_debug('expand_abbr abbr: %r result: %r' % (abbr, result)) + + if result: + return [(abbr, result, result)] + + except ZenInvalidAbbreviation: + pass # If it wasn't a valid Zen css snippet, or the prefix is empty '' # then get warm and fuzzy with css properties. diff --git a/ZenCoding/sublimezenplugin.pyc b/ZenCoding/sublimezenplugin.pyc deleted file mode 100644 index 794aa6a..0000000 Binary files a/ZenCoding/sublimezenplugin.pyc and /dev/null differ diff --git a/ZenCoding/zen-coding.sublime-settings b/ZenCoding/zen-coding.sublime-settings index 11eedc9..7aca23f 100644 --- a/ZenCoding/zen-coding.sublime-settings +++ b/ZenCoding/zen-coding.sublime-settings @@ -14,6 +14,10 @@ // "css_properties" ], + // Report some usage statistics + // (currently just platform/arch/version/bool(unicode in packages path) etc) + "zenarbitrage" : true, + // For those who just want `zen as you type`, disable completions entirely "disable_completions": false, @@ -24,11 +28,11 @@ // You don't copy the whole structure, but rather individual keys. // Inside the `File Settings` key. // | - // /^\ + // /^\ "File Settings" : { // README------^/ // README----->/ - // README----^/ + // README----^/ //>------------->/ // If `true` will disable ctrl+alt+n binding diff --git a/ZenCoding/zenarbitrage.py b/ZenCoding/zenarbitrage.py new file mode 100644 index 0000000..279ab5d --- /dev/null +++ b/ZenCoding/zenarbitrage.py @@ -0,0 +1,65 @@ +#coding: utf8 +#################################### IMPORTS ################################### + +import urllib2 +import urllib +import time + +import threading +import sublime +import json + +################################### CONSTANTS ################################## + +URL = 'http://gmh.akalias.net/doop.cgi' +WINDOWS = sublime.platform() == 'windows' + +########################### PLATFORM SPECIFIC IMPORTS ########################## + +if WINDOWS: from ctypes import windll, create_unicode_buffer + +#################################### HELPERS ################################### + +def importable_path(unicode_file_name): + try: + if WINDOWS: unicode_file_name.encode('ascii') + return unicode_file_name + except UnicodeEncodeError: + buf = create_unicode_buffer(512) + return( buf.value if ( + windll.kernel32 + .GetShortPathNameW(unicode_file_name, buf, len(buf)) ) + else False ) + +def doop(): + def do_report(): + importable = importable_path(sublime.packages_path()) + + data = { + "report" : json.dumps ({ + + 'arbitrage_version' : 3, + 'time' : time.ctime(), + + 'arch' : sublime.arch(), + 'platform' : sublime.platform(), + 'version' : sublime.version(), + 'channel' : sublime.channel(), + + 'packages_path' : sublime.packages_path(), + 'importable_path' : importable, + + 'unicode_sys_path_problem' : not importable, + })} + + req = urllib2.Request(URL, urllib.urlencode(data)) + urllib2.urlopen(req, timeout=2) + + def report(): + try: do_report() + except: pass + + t = threading.Thread(target=report) + t.start() + +################################################################################ \ No newline at end of file diff --git a/ZenCoding/zenarbitrage.pyc b/ZenCoding/zenarbitrage.pyc new file mode 100644 index 0000000..55e9da0 Binary files /dev/null and b/ZenCoding/zenarbitrage.pyc differ diff --git a/ZenCoding/zencoding/__init__.pyc b/ZenCoding/zencoding/__init__.pyc deleted file mode 100644 index 9af0168..0000000 Binary files a/ZenCoding/zencoding/__init__.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/actions/__init__.pyc b/ZenCoding/zencoding/actions/__init__.pyc deleted file mode 100644 index fefc82c..0000000 Binary files a/ZenCoding/zencoding/actions/__init__.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/actions/basic.py b/ZenCoding/zencoding/actions/basic.py index 6057154..fef9696 100644 --- a/ZenCoding/zencoding/actions/basic.py +++ b/ZenCoding/zencoding/actions/basic.py @@ -861,7 +861,7 @@ def _bounds(ch, start, content): num = content[r[0]:r[1]] num = zencoding.utils.prettify_number(float(num) + float(step)) # mark result as selection - editor.replace_content('${0:%s}' % num, r[0], r[1]); + editor.replace_content('${0:%s}' % num, r[0], r[1], escape=False); # editor.create_selection(r[0], r[0] + len(num)) return True except: diff --git a/ZenCoding/zencoding/actions/basic.pyc b/ZenCoding/zencoding/actions/basic.pyc deleted file mode 100644 index 8688e4b..0000000 Binary files a/ZenCoding/zencoding/actions/basic.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/actions/token.py b/ZenCoding/zencoding/actions/token.py index 8a83d72..bcd4125 100644 --- a/ZenCoding/zencoding/actions/token.py +++ b/ZenCoding/zencoding/actions/token.py @@ -17,397 +17,407 @@ @zencoding.action def reflect_css_value(editor): - """ - Reflect CSS value: takes rule's value under caret and pastes it for the same - rules with vendor prefixes - @param editor: ZenEditor - """ - if editor.get_syntax() != 'css': - return False - - return compound_update(editor, do_css_reflection(editor)) + """ + Reflect CSS value: takes rule's value under caret and pastes it for the same + rules with vendor prefixes + @param editor: ZenEditor + """ + if editor.get_syntax() != 'css': + return False + + return compound_update(editor, do_css_reflection(editor)) @zencoding.action def update_image_size(editor): - """ - Update image size: reads image from image/CSS rule under caret - and updates dimensions inside tag/rule - @type editor: ZenEditor - """ - if editor.get_syntax() == 'css': - result = update_image_size_css(editor) - else: - result = update_image_size_html(editor) - - return compound_update(editor, result) + """ + Update image size: reads image from image/CSS rule under caret + and updates dimensions inside tag/rule + @type editor: ZenEditor + """ + if editor.get_syntax() == 'css': + result = update_image_size_css(editor) + else: + result = update_image_size_html(editor) + + return compound_update(editor, result) def compound_update(editor, data): - if data: - text = data['data'] - - sel_start, sel_end = editor.get_selection_range() - - # try to preserve caret position - if data['caret'] < data['start'] + len(text): - relative_pos = data['caret'] - data['start'] - if relative_pos >= 0: - text = text[:relative_pos] + zencoding.utils.get_caret_placeholder() + text[relative_pos:] - - editor.replace_content(text, data['start'], data['end'], True) -# editor.replace_content(zencoding.utils.unindent(editor, text), data['start'], data['end']) - editor.create_selection(data['caret'], data['caret'] + sel_end - sel_start) - return True - - return False + if data: + text = data['data'] + + sel_start, sel_end = editor.get_selection_range() + + # try to preserve caret position + if data['caret'] < data['start'] + len(text): + relative_pos = data['caret'] - data['start'] + if relative_pos >= 0: + text = text[:relative_pos] + zencoding.utils.get_caret_placeholder() + text[relative_pos:] + + editor.replace_content(text, data['start'], data['end'], True) +# editor.replace_content(zencoding.utils.unindent(editor, text), data['start'], data['end']) + editor.create_selection(data['caret'], data['caret'] + sel_end - sel_start) + return True + + return False def update_image_size_html(editor): - """ - Updates image size of <img src=""> tag - @type editor: ZenEditor - """ - editor_file = editor.get_file_path() - caret_pos = editor.get_caret_pos() - - if editor_file is None: - raise zencoding.utils.ZenError("You should save your file before using this action") - - image = _find_image(editor) - - if image: - # search for image path - m = re.search(r'src=(["\'])(.+?)\1', image['tag'], re.IGNORECASE) - if m: - src = m.group(2) - - if src: - size = get_image_size_for_source(editor, src) - if size: - new_tag = _replace_or_append(image['tag'], 'width', size['width']) - new_tag = _replace_or_append(new_tag, 'height', size['height']) - - return { - 'data': new_tag, - 'start': image['start'], - 'end': image['end'], - 'caret': caret_pos - } - return False + """ + Updates image size of <img src=""> tag + @type editor: ZenEditor + """ + editor_file = editor.get_file_path() + caret_pos = editor.get_caret_pos() + + if editor_file is None: + raise zencoding.utils.ZenError("You should save your file before using this action") + + image = _find_image(editor) + + if image: + # search for image path + m = re.search(r'src=(["\'])(.+?)\1', image['tag'], re.IGNORECASE) + if m: + src = m.group(2) + + if src: + size = get_image_size_for_source(editor, src) + if size: + new_tag = _replace_or_append(image['tag'], 'width', size['width']) + new_tag = _replace_or_append(new_tag, 'height', size['height']) + + return { + 'data': new_tag, + 'start': image['start'], + 'end': image['end'], + 'caret': caret_pos + } + return False def get_image_size_for_source(editor, src): - """ - Returns image dimentions for source - @param {zen_editor} editor - @param {String} src Image source (path or data:url) - """ - if src: - # check if it is data:url - if starts_with('data:', src): - f_content = base64.b64decode( re.sub(r'^data\:.+?;.+?,', '', src) ) - else: - editor_file = editor.get_file_path() - - if editor_file is None: - raise zencoding.utils.ZenError("You should save your file before using this action") - - abs_src = zen_file.locate_file(editor_file, src) - if not abs_src: - raise zencoding.utils.ZenError("Can't locate '%s' file" % src) - - f_content = zen_file.read(abs_src) - - return zencoding.utils.get_image_size(f_content) + """ + Returns image dimentions for source + @param {zen_editor} editor + @param {String} src Image source (path or data:url) + """ + if src: + # check if it is data:url + if starts_with('data:', src): + f_content = base64.b64decode( re.sub(r'^data\:.+?;.+?,', '', src) ) + else: + editor_file = editor.get_file_path() + + if editor_file is None: + raise zencoding.utils.ZenError("You should save your file before using this action") + + abs_src = zen_file.locate_file(editor_file, src) + if not abs_src: + raise zencoding.utils.ZenError("Can't locate '%s' file" % src) + + f_content = zen_file.read(abs_src) + + return zencoding.utils.get_image_size(f_content) def _replace_or_append(img_tag, attr_name, attr_value): - """ - Replaces or adds attribute to the tag - @type img_tag: str - @type attr_name: str - @type attr_value: str - """ - if attr_name in img_tag.lower(): - # attribute exists - re_attr = re.compile(attr_name + r'=([\'"])(.*?)\1', re.I) - return re.sub(re_attr, lambda m: '%s=%s%s%s' % (attr_name, m.group(1), attr_value, m.group(1)), img_tag) - else: - return re.sub(r'\s*(\/?>)$', ' %s="%s" \\1' % (attr_name, attr_value), img_tag) + """ + Replaces or adds attribute to the tag + @type img_tag: str + @type attr_name: str + @type attr_value: str + """ + if attr_name in img_tag.lower(): + # attribute exists + re_attr = re.compile(attr_name + r'=([\'"])(.*?)\1', re.I) + return re.sub(re_attr, lambda m: '%s=%s%s%s' % (attr_name, m.group(1), attr_value, m.group(1)), img_tag) + else: + return re.sub(r'\s*(\/?>)$', ' %s="%s" \\1' % (attr_name, attr_value), img_tag) def _find_image(editor): - """ - Find image tag under caret - @return Image tag and its indexes inside editor source - """ - _caret = editor.get_caret_pos() - text = editor.get_content() - start_ix = -1 - end_ix = -1 - - # find the beginning of the tag - caret_pos = _caret - while caret_pos >= 0: - if text[caret_pos] == '<': - if text[caret_pos:caret_pos + 4].lower() == '': - end_ix = caret_pos + 1 - break - caret_pos += 1 - - - if start_ix != -1 and end_ix != -1: - return { - 'start': start_ix, - 'end': end_ix, - 'tag': text[start_ix:end_ix] - } - - return None + """ + Find image tag under caret + @return Image tag and its indexes inside editor source + """ + _caret = editor.get_caret_pos() + text = editor.get_content() + start_ix = -1 + end_ix = -1 + + # find the beginning of the tag + caret_pos = _caret + while caret_pos >= 0: + if text[caret_pos] == '<': + if text[caret_pos:caret_pos + 4].lower() == '': + end_ix = caret_pos + 1 + break + caret_pos += 1 + + + if start_ix != -1 and end_ix != -1: + return { + 'start': start_ix, + 'end': end_ix, + 'tag': text[start_ix:end_ix] + } + + return None def find_css_insertion_point(tokens, start_ix): - """ - Search for insertion point for new CSS properties - @param tokens: List of parsed CSS tokens - @param start_ix: Token index where to start searching - """ - ins_point = None - ins_ix = -1 - need_col = False - - for i in range(start_ix, len(tokens)): - t = tokens[i] - if t['type'] == 'value': - ins_point = t - ins_ix = i - - # look ahead for rule termination - if i + 1 < len(tokens) and tokens[i + 1]['type'] == ';': - ins_point = tokens[i + 1] - ins_ix += 1 - else: - need_col = True - - break - - return { - 'token': ins_point, - 'ix': ins_ix, - 'need_col': need_col - } + """ + Search for insertion point for new CSS properties + @param tokens: List of parsed CSS tokens + @param start_ix: Token index where to start searching + """ + ins_point = None + ins_ix = -1 + need_col = False + + for i in range(start_ix, len(tokens)): + t = tokens[i] + if t['type'] == 'value': + ins_point = t + ins_ix = i + + # look ahead for rule termination + if i + 1 < len(tokens) and tokens[i + 1]['type'] == ';': + ins_point = tokens[i + 1] + ins_ix += 1 + else: + need_col = True + + break + + return { + 'token': ins_point, + 'ix': ins_ix, + 'need_col': need_col + } def update_image_size_css(editor): - """ - Updates image size of CSS rule - @type editor: ZenEditor - """ - caret_pos = editor.get_caret_pos() - content = editor.get_content() - rule = parser_utils.extract_css_rule(content, caret_pos, True) - - if rule: - css = parser_utils.parse_css(content[rule[0]:rule[1]], rule[0]) - cur_token = find_token_from_position(css, caret_pos, 'identifier') - value = find_value_token(css, cur_token + 1) - - if not value: return False - - # find insertion point - ins_point = find_css_insertion_point(css, cur_token) - - m = re.match(r'url\((["\']?)(.+?)\1\)', value['content'], re.I) - if m: - size = get_image_size_for_source(editor, m.group(2)) - if size: - wh = {'width': None, 'height': None} - updates = [] - styler = learn_css_style(css, cur_token) - - for i, item in enumerate(css): - if item['type'] == 'identifier' and item['content'] in wh: - wh[item['content']] = i - - def update(name, val): - v = None - if wh[name] is not None: - v = find_value_token(css, wh[name] + 1) - - if v: - updates.append([v['start'], v['end'], '%spx' % val]) - else: - updates.append([ins_point['token']['end'], ins_point['token']['end'], styler(name, '%spx' % val)]) - - - update('width', size['width']) - update('height', size['height']) - - if updates: - updates.sort(lambda a,b: a[0] - b[0]) -# updates = sorted(updates, key=lambda a: a[0]) - - # some editors do not provide easy way to replace multiple code - # fragments so we have to squash all replace operations into one - offset = updates[0][0] - offset_end = updates[-1][1] - data = content[offset:offset_end] - - updates.reverse() - for u in updates: - data = replace_substring(data, u[0] - offset, u[1] - offset, u[2]) - - # also calculate new caret position - if u[0] < caret_pos: - caret_pos += len(u[2]) - u[1] + u[0] - - - if ins_point['need_col']: - data = replace_substring(data, ins_point['token']['end'] - offset, ins_point['token']['end'] - offset, ';') - - return { - 'data': data, - 'start': offset, - 'end': offset_end, - 'caret': caret_pos - }; - - return None + """ + Updates image size of CSS rule + @type editor: ZenEditor + """ + caret_pos = editor.get_caret_pos() + content = editor.get_content() + rule = parser_utils.extract_css_rule(content, caret_pos, True) + + if rule: + css = parser_utils.parse_css(content[rule[0]:rule[1]], rule[0]) + cur_token = find_token_from_position(css, caret_pos, 'identifier') + value = find_value_token(css, cur_token + 1) + + if not value: return False + + # find insertion point + ins_point = find_css_insertion_point(css, cur_token) + + m = re.match(r'url\((["\']?)(.+?)\1\)', value['content'], re.I) + if m: + size = get_image_size_for_source(editor, m.group(2)) + if size: + wh = {'width': None, 'height': None} + updates = [] + styler = learn_css_style(css, cur_token) + + for i, item in enumerate(css): + if item['type'] == 'identifier' and item['content'] in wh: + wh[item['content']] = i + + def update(name, val): + v = None + if wh[name] is not None: + v = find_value_token(css, wh[name] + 1) + + if v: + updates.append([v['start'], v['end'], '%spx' % val]) + else: + updates.append([ins_point['token']['end'], ins_point['token']['end'], styler(name, '%spx' % val)]) + + + update('width', size['width']) + update('height', size['height']) + + if updates: + updates.sort(lambda a,b: a[0] - b[0]) +# updates = sorted(updates, key=lambda a: a[0]) + + # some editors do not provide easy way to replace multiple code + # fragments so we have to squash all replace operations into one + offset = updates[0][0] + offset_end = updates[-1][1] + data = content[offset:offset_end] + + updates.reverse() + for u in updates: + data = replace_substring(data, u[0] - offset, u[1] - offset, u[2]) + + # also calculate new caret position + if u[0] < caret_pos: + caret_pos += len(u[2]) - u[1] + u[0] + + + if ins_point['need_col']: + data = replace_substring(data, ins_point['token']['end'] - offset, ins_point['token']['end'] - offset, ';') + + return { + 'data': data, + 'start': offset, + 'end': offset_end, + 'caret': caret_pos + }; + + return None def learn_css_style(tokens, pos): - """ - Learns formatting style from parsed tokens - @param tokens: List of tokens - @param pos: Identifier token position, from which style should be learned - @returns: Function with (name, value) arguments that will create - CSS rule based on learned formatting - """ - prefix = '' - glue = '' - - # use original tokens instead of optimized ones - pos = tokens[pos]['ref_start_ix'] - tokens = tokens.original - - # learn prefix - for i in xrange(pos - 1, -1, -1): - if tokens[i]['type'] == 'white': - prefix = tokens[i]['content'] + prefix - elif tokens[i]['type'] == 'line': - prefix = tokens[i]['content'] + prefix - break - else: - break - - # learn glue - for t in tokens[pos+1:]: - if t['type'] == 'white' or t['type'] == ':': - glue += t['content'] - else: - break - - if ':' not in glue: - glue = ':' - - return lambda name, value: "%s%s%s%s;" % (prefix, name, glue, value) - + """ + Learns formatting style from parsed tokens + @param tokens: List of tokens + @param pos: Identifier token position, from which style should be learned + @returns: Function with (name, value) arguments that will create + CSS rule based on learned formatting + """ + prefix = '' + glue = '' + + # use original tokens instead of optimized ones + pos = tokens[pos]['ref_start_ix'] + tokens = tokens.original + + # learn prefix + for i in xrange(pos - 1, -1, -1): + if tokens[i]['type'] == 'white': + prefix = tokens[i]['content'] + prefix + elif tokens[i]['type'] == 'line': + prefix = tokens[i]['content'] + prefix + break + else: + break + + # learn glue + for t in tokens[pos+1:]: + if t['type'] == 'white' or t['type'] == ':': + glue += t['content'] + else: + break + + if ':' not in glue: + glue = ':' + + return lambda name, value: "%s%s%s%s;" % (prefix, name, glue, value) + def do_css_reflection(editor): - content = editor.get_content() - caret_pos = editor.get_caret_pos() - css = parser_utils.extract_css_rule(content, caret_pos) - - if not css or caret_pos < css[0] or caret_pos > css[1]: - # no matching CSS rule or caret outside rule bounds - return False - - tokens = parser_utils.parse_css(content[css[0]:css[1]], css[0]) - token_ix = find_token_from_position(tokens, caret_pos, 'identifier') - - if token_ix != -1: - cur_prop = tokens[token_ix]['content'] - value_token = find_value_token(tokens, token_ix + 1) - base_name = get_base_css_name(cur_prop) - re_name = re.compile('^(?:\\-\\w+\\-)?' + base_name + '$') - re_name = get_reflected_css_name(base_name) - values = [] - - if not value_token: - return False - - # search for all vendor-prefixed properties - for i, token in enumerate(tokens): - if token['type'] == 'identifier' and re.search(re_name, token['content']) and token['content'] != cur_prop: - v = find_value_token(tokens, i + 1) - if v: - values.append({'name': token, 'value': v}) - - # some editors do not provide easy way to replace multiple code - # fragments so we have to squash all replace operations into one - if values: - data = content[values[0]['value']['start']:values[-1]['value']['end']] - offset = values[0]['value']['start'] - value = value_token['content'] - - values.reverse() - for v in values: - rv = get_reflected_value(cur_prop, value, v['name']['content'], v['value']['content']) - data = replace_substring(data, v['value']['start'] - offset, v['value']['end'] - offset, rv) - - # also calculate new caret position - if v['value']['start'] < caret_pos: - caret_pos += len(rv) - len(v['value']['content']) - - return { - 'data': data, - 'start': offset, - 'end': values[0]['value']['end'], - 'caret': caret_pos - } - - return None + content = editor.get_content() + caret_pos = editor.get_caret_pos() + css = parser_utils.extract_css_rule(content, caret_pos) + + if not css or caret_pos < css[0] or caret_pos > css[1]: + # no matching CSS rule or caret outside rule bounds + return False + + tokens = parser_utils.parse_css(content[css[0]:css[1]], css[0]) + token_ix = find_token_from_position(tokens, caret_pos, 'identifier') + + if token_ix != -1: + cur_prop = tokens[token_ix]['content'] + value_token = find_value_token(tokens, token_ix + 1) + base_name = get_base_css_name(cur_prop) + re_name = re.compile('^(?:\\-\\w+\\-)?' + base_name + '$') + re_name = get_reflected_css_name(base_name) + values = [] + + if not value_token: + return False + + # search for all vendor-prefixed properties + for i, token in enumerate(tokens): + if token['type'] == 'identifier': + if re_name.search(token['content']): + # print token + # v = find_value_token(tokens, i + 1) + # value = value_token['content'] + # rv = get_reflected_value(cur_prop, value, token['content'], v['content']) + # print rv + + if token['content'] != cur_prop: + v = find_value_token(tokens, i + 1) + if v: + values.append({'name': token, 'value': v}) + + # some editors do not provide easy way to replace multiple code + # fragments so we have to squash all replace operations into one + if values: + print values + + data = content[values[0]['value']['start']:values[-1]['value']['end']] + offset = values[0]['value']['start'] + value = value_token['content'] + + values.reverse() + for v in values: + rv = get_reflected_value(cur_prop, value, v['name']['content'], v['value']['content']) + data = replace_substring(data, v['value']['start'] - offset, v['value']['end'] - offset, rv) + + # also calculate new caret position + if v['value']['start'] < caret_pos: + caret_pos += len(rv) - len(v['value']['content']) + + return { + 'data': data, + 'start': offset, + 'end': values[0]['value']['end'], + 'caret': caret_pos + } + + return None def get_base_css_name(name): - """ + """ Removes vendor prefix from CSS property @param name: CSS property @type name: str @return: str - """ - return re.sub(r'^\s*\-\w+\-', '', name) + """ + return re.sub(r'^\s*\-\w+\-', '', name) def get_reflected_css_name(name): - """ + """ Returns regexp that should match reflected CSS property names @param name: Current CSS property name @type name: str @return: RegExp - """ - name = get_base_css_name(name) - vendor_prefix = '^(?:\\-\\w+\\-)?' - - if name == 'opacity' or name == 'filter': - return re.compile(vendor_prefix + '(?:opacity|filter)$') - - m = re.match(r'^border-radius-(top|bottom)(left|right)', name) - if m: - # Mozilla-style border radius - return re.compile(vendor_prefix + '(?:%s|border-%s-%s-radius)$' % (name, m.group(1), m.group(2)) ) - - m = re.match(r'^border-(top|bottom)-(left|right)-radius', name) - if m: - return re.compile(vendor_prefix + '(?:%s|border-radius-%s%s)$' % (name, m.group(1), m.group(2)) ); - - return re.compile(vendor_prefix + name + '$') + """ + name = get_base_css_name(name) + vendor_prefix = '^(?:\\-\\w+\\-)?' + + if name == 'opacity' or name == 'filter': + return re.compile(vendor_prefix + '(?:opacity|filter)$') + + m = re.match(r'^border-radius-(top|bottom)(left|right)', name) + if m: + # Mozilla-style border radius + return re.compile(vendor_prefix + '(?:%s|border-%s-%s-radius)$' % (name, m.group(1), m.group(2)) ) + + m = re.match(r'^border-(top|bottom)-(left|right)-radius', name) + if m: + return re.compile(vendor_prefix + '(?:%s|border-radius-%s%s)$' % (name, m.group(1), m.group(2)) ); + + return re.compile(vendor_prefix + name + '$') def get_reflected_value(cur_name, cur_value, ref_name, ref_value): - """ + """ Returns value that should be reflected for ref_name CSS property from cur_name property. This function is used for special cases, when the same result must be achieved with different properties for different @@ -424,36 +434,35 @@ def get_reflected_value(cur_name, cur_value, ref_name, ref_value): @param ref_value: Receiver CSS property's value @type ref_value: str @return: New value for receiver property - """ - cur_name = get_base_css_name(cur_name) - ref_name = get_base_css_name(ref_name) - - if cur_name == 'opacity' and ref_name == 'filter': - return re.sub(re.compile(r'opacity=[^\)]*', re.IGNORECASE), 'opacity=' + math.floor(float(cur_value) * 100), ref_value) - if cur_name == 'filter' and ref_name == 'opacity': - m = re.search(r'opacity=([^\)]*)', cur_value, re.IGNORECASE) - return prettify_number(int(m.group(1)) / 100) if m else ref_value - - - return cur_value + """ + cur_name = get_base_css_name(cur_name) + ref_name = get_base_css_name(ref_name) + + if cur_name == 'opacity' and ref_name == 'filter': + return re.sub(re.compile(r'opacity=[^\)]*', re.IGNORECASE), 'opacity=%s' % math.floor(float(cur_value) * 100), ref_value) + if cur_name == 'filter' and ref_name == 'opacity': + m = re.search(r'opacity=([^\)]*)', cur_value, re.IGNORECASE) + return prettify_number(int(m.group(1)) / 100) if m else ref_value + + return cur_value def find_value_token(tokens, pos): - """ + """ Find value token, staring at pos index and moving right @type tokens: list @type pos: int @return: token - """ - for t in tokens[pos:]: - if t['type'] == 'value': - return t - elif t['type'] == 'identifier' or t['type'] == ';': - break - - return None + """ + for t in tokens[pos:]: + if t['type'] == 'value': + return t + elif t['type'] == 'identifier' or t['type'] == ';': + break + + return None def replace_substring(text, start, end, new_value): - """ + """ Replace substring of text, defined by start and end indexes with new_value @type text: str @@ -461,11 +470,11 @@ def replace_substring(text, start, end, new_value): @type end: int @type new_value: str @return: str - """ - return text[0:start] + new_value + text[end:] + """ + return text[0:start] + new_value + text[end:] def find_token_from_position(tokens, pos, type): - """ + """ Search for token with specified type left to the specified position @param tokens: List of parsed tokens @type tokens: list @@ -474,19 +483,19 @@ def find_token_from_position(tokens, pos, type): @param type: Token type @type type: str @return: Token index - """ - # find token under caret - token_ix = -1; - for i, token in enumerate(tokens): - if token['start'] <= pos and token['end'] >= pos: - token_ix = i - break - - if token_ix != -1: - # token found, search left until we find token with specified type - while token_ix >= 0: - if tokens[token_ix]['type'] == type: - return token_ix - token_ix -= 1 - - return -1 + """ + # find token under caret + token_ix = -1; + for i, token in enumerate(tokens): + if token['start'] <= pos and token['end'] >= pos: + token_ix = i + break + + if token_ix != -1: + # token found, search left until we find token with specified type + while token_ix >= 0: + if tokens[token_ix]['type'] == type: + return token_ix + token_ix -= 1 + + return -1 diff --git a/ZenCoding/zencoding/actions/token.pyc b/ZenCoding/zencoding/actions/token.pyc deleted file mode 100644 index 9a3d17d..0000000 Binary files a/ZenCoding/zencoding/actions/token.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/actions/traverse.pyc b/ZenCoding/zencoding/actions/traverse.pyc deleted file mode 100644 index 2606ed3..0000000 Binary files a/ZenCoding/zencoding/actions/traverse.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/__init__.pyc b/ZenCoding/zencoding/filters/__init__.pyc deleted file mode 100644 index fb2cc14..0000000 Binary files a/ZenCoding/zencoding/filters/__init__.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/comment.pyc b/ZenCoding/zencoding/filters/comment.pyc deleted file mode 100644 index 061439c..0000000 Binary files a/ZenCoding/zencoding/filters/comment.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/css.pyc b/ZenCoding/zencoding/filters/css.pyc deleted file mode 100644 index 5ad5956..0000000 Binary files a/ZenCoding/zencoding/filters/css.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/escape.pyc b/ZenCoding/zencoding/filters/escape.pyc deleted file mode 100644 index 8b8e40c..0000000 Binary files a/ZenCoding/zencoding/filters/escape.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/format-css.pyc b/ZenCoding/zencoding/filters/format-css.pyc deleted file mode 100644 index b4fa654..0000000 Binary files a/ZenCoding/zencoding/filters/format-css.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/format.pyc b/ZenCoding/zencoding/filters/format.pyc deleted file mode 100644 index 08ba4c3..0000000 Binary files a/ZenCoding/zencoding/filters/format.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/haml.pyc b/ZenCoding/zencoding/filters/haml.pyc deleted file mode 100644 index 9dd646e..0000000 Binary files a/ZenCoding/zencoding/filters/haml.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/html.pyc b/ZenCoding/zencoding/filters/html.pyc deleted file mode 100644 index 3c87837..0000000 Binary files a/ZenCoding/zencoding/filters/html.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/single-line.pyc b/ZenCoding/zencoding/filters/single-line.pyc deleted file mode 100644 index 66c2966..0000000 Binary files a/ZenCoding/zencoding/filters/single-line.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/stylus.py b/ZenCoding/zencoding/filters/stylus.py new file mode 100644 index 0000000..f2a4df7 --- /dev/null +++ b/ZenCoding/zencoding/filters/stylus.py @@ -0,0 +1,10 @@ +import zencoding + +@zencoding.filter('stylus') +def process(tree, profile): + for item in tree.children: + # CSS properties are always snippets + if item.type == 'snippet': + item.start = item.start.rstrip(';') + process(item, profile) + return tree \ No newline at end of file diff --git a/ZenCoding/zencoding/filters/stylus.pyc b/ZenCoding/zencoding/filters/stylus.pyc new file mode 100644 index 0000000..db5d6c4 Binary files /dev/null and b/ZenCoding/zencoding/filters/stylus.pyc differ diff --git a/ZenCoding/zencoding/filters/trim.pyc b/ZenCoding/zencoding/filters/trim.pyc deleted file mode 100644 index 87f1b7a..0000000 Binary files a/ZenCoding/zencoding/filters/trim.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/filters/xsl.pyc b/ZenCoding/zencoding/filters/xsl.pyc deleted file mode 100644 index b0cc0a8..0000000 Binary files a/ZenCoding/zencoding/filters/xsl.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/html_matcher.pyc b/ZenCoding/zencoding/html_matcher.pyc deleted file mode 100644 index 2a3a070..0000000 Binary files a/ZenCoding/zencoding/html_matcher.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/interface/__init__.pyc b/ZenCoding/zencoding/interface/__init__.pyc deleted file mode 100644 index 39fa1b8..0000000 Binary files a/ZenCoding/zencoding/interface/__init__.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/interface/editor.py b/ZenCoding/zencoding/interface/editor.py index 2f86be9..ac21fe7 100644 --- a/ZenCoding/zencoding/interface/editor.py +++ b/ZenCoding/zencoding/interface/editor.py @@ -26,7 +26,7 @@ def active_view(): ################################################################################ class ZenEditor(): - def expand_abbr(self, abbr, syntax = None, selection=True, + def expand_abbr(self, abbr, syntax = None, selection=True, super_profile=None): syntax = syntax or self.get_syntax() @@ -74,7 +74,7 @@ def create_selection(self, start=None, end=None, sels=[]): zen_editor.create_selection(15) """ - + view = active_view() view.sel().clear() @@ -119,7 +119,8 @@ def get_current_line(self): view = active_view() return view.substr(view.line(view.sel()[0])) - def replace_content(self, value, start=None, end=None, zero_stops=False): + def replace_content(self, value, start=None, end=None, zero_stops=False, + escape = True): """ Replace editor's content or it's part (from *start* to *end* index). If *value* contains @@ -150,8 +151,14 @@ def replace_content(self, value, start=None, end=None, zero_stops=False): self.create_selection(start, end) - value = value.replace('$', r'\$') - value = self.add_placeholders(value, selection=0, explicit_zero=zero_stops) + # print value + if escape: + value = value.replace('$', r'\$') + + value = self.add_placeholders(value, + selection = 0, + explicit_zero = zero_stops + ) if '\n' in value: for sel in view.sel(): @@ -184,7 +191,8 @@ def get_syntax(self): if 'xsl' in scope: doc_type = 'xsl' else: - doc_type = re.findall(r'\bhtml|js|css|xml|haml\b', scope)[0] + doc_type = re.findall(r'\bhtml|js|css|xml|haml|stylus\b', scope)[0] + # if doc_type == 'stylus': doc_type = 'css' # Sublime has back to front scopes .... except: doc_type = default_type diff --git a/ZenCoding/zencoding/interface/editor.pyc b/ZenCoding/zencoding/interface/editor.pyc deleted file mode 100644 index 2d5881c..0000000 Binary files a/ZenCoding/zencoding/interface/editor.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/interface/file.pyc b/ZenCoding/zencoding/interface/file.pyc deleted file mode 100644 index 3818dad..0000000 Binary files a/ZenCoding/zencoding/interface/file.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/parser/__init__.pyc b/ZenCoding/zencoding/parser/__init__.pyc deleted file mode 100644 index e36c7fd..0000000 Binary files a/ZenCoding/zencoding/parser/__init__.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/parser/abbreviation.pyc b/ZenCoding/zencoding/parser/abbreviation.pyc deleted file mode 100644 index 0a2e97d..0000000 Binary files a/ZenCoding/zencoding/parser/abbreviation.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/parser/css.pyc b/ZenCoding/zencoding/parser/css.pyc deleted file mode 100644 index 83480e8..0000000 Binary files a/ZenCoding/zencoding/parser/css.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/parser/utils.pyc b/ZenCoding/zencoding/parser/utils.pyc deleted file mode 100644 index 2d8a16c..0000000 Binary files a/ZenCoding/zencoding/parser/utils.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/parser/xml.pyc b/ZenCoding/zencoding/parser/xml.pyc deleted file mode 100644 index 99e9f3c..0000000 Binary files a/ZenCoding/zencoding/parser/xml.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/resources.py b/ZenCoding/zencoding/resources.py index 942113f..8f70f96 100644 --- a/ZenCoding/zencoding/resources.py +++ b/ZenCoding/zencoding/resources.py @@ -98,7 +98,6 @@ def create_resource_chain(vocabulary, syntax, name): if name in resource: result.append(resource[name]) - # get inheritance definition # in case of user-defined vocabulary, resource dependency # may be defined in system vocabulary only, so we have to correctly diff --git a/ZenCoding/zencoding/resources.pyc b/ZenCoding/zencoding/resources.pyc deleted file mode 100644 index ec5dea7..0000000 Binary files a/ZenCoding/zencoding/resources.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/utils.pyc b/ZenCoding/zencoding/utils.pyc deleted file mode 100644 index 174e5a4..0000000 Binary files a/ZenCoding/zencoding/utils.pyc and /dev/null differ diff --git a/ZenCoding/zencoding/zen_settings.pyc b/ZenCoding/zencoding/zen_settings.pyc deleted file mode 100644 index 752cb67..0000000 Binary files a/ZenCoding/zencoding/zen_settings.pyc and /dev/null differ diff --git a/ZenCoding/zenmeta.pyc b/ZenCoding/zenmeta.pyc deleted file mode 100644 index 7804446..0000000 Binary files a/ZenCoding/zenmeta.pyc and /dev/null differ diff --git a/ZenCoding/zentrackers.pyc b/ZenCoding/zentrackers.pyc deleted file mode 100644 index 87c0494..0000000 Binary files a/ZenCoding/zentrackers.pyc and /dev/null differ diff --git a/sublimelint/.gitignore b/sublimelint/.gitignore deleted file mode 100644 index 5c64234..0000000 --- a/sublimelint/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.DS_Store -*.pyc -*.sublime-project \ No newline at end of file diff --git a/sublimelint/README.markdown b/sublimelint/README.markdown deleted file mode 100644 index 6155257..0000000 --- a/sublimelint/README.markdown +++ /dev/null @@ -1,39 +0,0 @@ -Sublime Lint -========= - -A code-validating plugin with inline highlighting for the [Sublime Text 2](http://sublimetext.com "Sublime Text 2") editor. - -Supports the following languages: - -* Python - native, moderately-complete lint - -NOTE: the following languages may require you to install additional binaries and place them within your PATH (environment variable) - -* Coffescript - validation via "coffee --compile" -* Java - validation via "java -Xlint" and a temporary file -* PHP - syntax checking via "php -l" -* Perl - syntax+deprecation checking via "perl -c" -* Ruby - syntax checking via "ruby -wc" - - -Installing ------ - -*Without Git:* Download the latest source and copy sublimelint_plugin.py and the sublimelint/ folder to your Sublime Text "User" packages directory. - -*With Git:* Clone the repository in your Sublime Text Packages directory (located one folder above the "User" directory) - -> git clone git://github.com/lunixbochs/sublimelint.git - ----- - -The "User" packages directory is located at: - -* Windows: - %APPDATA%/Sublime Text 2/Packages/User/ -* OS X: - ~/Library/Application Support/Sublime Text 2/Packages/User/ -* Linux: - ~/.config/sublime-text-2/User - -You can also use the Preferences menu to open Package directories. \ No newline at end of file diff --git a/sublimelint/package-metadata.json b/sublimelint/package-metadata.json deleted file mode 100644 index c2295c7..0000000 --- a/sublimelint/package-metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"url": "https://github.com/lunixbochs/sublimelint", "version": "2011.12.20.11.36.04", "description": "Inline lint highlighting for the Sublime Text editor"} \ No newline at end of file diff --git a/sublimelint/sublimelint/__init__.py b/sublimelint/sublimelint/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/sublimelint/sublimelint/modules/__init__.py b/sublimelint/sublimelint/modules/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/sublimelint/sublimelint/modules/coffee.py b/sublimelint/sublimelint/modules/coffee.py deleted file mode 100644 index bba08d5..0000000 --- a/sublimelint/sublimelint/modules/coffee.py +++ /dev/null @@ -1,55 +0,0 @@ -# coffee.py - sublimelint package for checking coffee-script files - -import subprocess, os - -def check(codeString, filename): - info = None - if os.name == 'nt': - info = subprocess.STARTUPINFO() - info.dwFlags |= subprocess.STARTF_USESHOWWINDOW - info.wShowWindow = subprocess.SW_HIDE - - process = subprocess.Popen( - ('coffee', '--compile', '--stdio'), - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - startupinfo=info - ) - result = process.communicate(codeString)[1] - return result - -import re -__all__ = ['run', 'language'] -language = 'CoffeeScript' - -compile_err = re.compile('^[A-Za-z]+: (.+) on line ([0-9]+)') - -def run(code, view, filename='untitled'): - errors = check(code, filename) - - lines = set() - underline = [] # leave this here for compatibility with original plugin - - errorMessages = {} - def addMessage(lineno, message): - message = str(message) - if lineno in errorMessages: - errorMessages[lineno].append(message) - else: - errorMessages[lineno] = [message] - - for line in errors.splitlines(): - match = compile_err.match(line) - if match: - error, line = match.groups() - else: - continue - - lineno = int(line) - 1 - lines.add(lineno) - addMessage(lineno, error) - - return underline, lines, errorMessages, True - -if __name__ == '__main__': - import sys - print run(open(sys.argv[1]).read(), 'bah') diff --git a/sublimelint/sublimelint/modules/java.py b/sublimelint/sublimelint/modules/java.py deleted file mode 100644 index 10e285f..0000000 --- a/sublimelint/sublimelint/modules/java.py +++ /dev/null @@ -1,69 +0,0 @@ -# coffee.py - sublimelint package for checking coffee-script files - -import subprocess, os, tempfile, shutil - -def check(codeString, filename): - if filename is None: return '' # can't check an unsaved file. - - info = None - if os.name == 'nt': - info = subprocess.STARTUPINFO() - info.dwFlags |= subprocess.STARTF_USESHOWWINDOW - info.wShowWindow = subprocess.SW_HIDE - - tempdir = tempfile.mkdtemp() - temp = os.path.join(tempdir, os.path.basename(filename)) - - tempout = open(temp, 'w') - tempout.write(codeString) - tempout.flush() - tempout.close() - - try: - process = subprocess.Popen( - ('javac', '-Xlint', temp), - stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - startupinfo=info - ) - result = process.communicate('')[1] - finally: - shutil.rmtree(tempdir) - - return result - -import re -__all__ = ['run', 'language'] -language = 'Java' - -compile_err = re.compile('^[^:]+:([0-9]+): +(.*)$') - -def run(code, view, filename='untitled'): - errors = check(code, filename) - - lines = set() - underline = [] # leave this here for compatibility with original plugin - - errorMessages = {} - def addMessage(lineno, message): - message = str(message) - if lineno in errorMessages: - errorMessages[lineno].append(message) - else: - errorMessages[lineno] = [message] - - for line in errors.splitlines(): - match = compile_err.match(line) - if match: - line, error = match.groups() - else: - continue - - lineno = int(line) - 1 - lines.add(lineno) - addMessage(lineno, error) - - return underline, lines, errorMessages, True - -if __name__ == '__main__': - import sys - print run(open(sys.argv[1]).read(), 'bah', sys.argv[1]) diff --git a/sublimelint/sublimelint/modules/perl.py b/sublimelint/sublimelint/modules/perl.py deleted file mode 100644 index 253b10b..0000000 --- a/sublimelint/sublimelint/modules/perl.py +++ /dev/null @@ -1,84 +0,0 @@ -# perl.py - sublimelint package for checking perl files - -import subprocess, os -import sublime - -def check(codeString, filename): - info = None - if os.name == 'nt': - info = subprocess.STARTUPINFO() - info.dwFlags |= subprocess.STARTF_USESHOWWINDOW - info.wShowWindow = subprocess.SW_HIDE - - process = subprocess.Popen(('perl', '-c'), - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - startupinfo=info) - result = process.communicate(codeString)[0] - - return result - -# start sublimelint perl plugin -import re -__all__ = ['run', 'language'] -language = 'Perl' - -def run(code, view, filename='untitled'): - errors = check(code, filename) - - lines = set() - underline = [] # leave this here for compatibility with original plugin - - errorMessages = {} - def addMessage(lineno, message): - message = str(message) - if lineno in errorMessages: - errorMessages[lineno].append(message) - else: - errorMessages[lineno] = [message] - - def underlineRange(lineno, position, length=1): - line = view.full_line(view.text_point(lineno, 0)) - position += line.begin() - - for i in xrange(length): - underline.append(sublime.Region(position + i)) - - def underlineRegex(lineno, regex, wordmatch=None, linematch=None): - lines.add(lineno) - offset = 0 - - line = view.full_line(view.text_point(lineno, 0)) - lineText = view.substr(line) - if linematch: - match = re.match(linematch, lineText) - if match: - lineText = match.group('match') - offset = match.start('match') - else: - return - - iters = re.finditer(regex, lineText) - results = [(result.start('underline'), result.end('underline')) for result in iters if - not wordmatch or result.group('underline') == wordmatch] - - for start, end in results: - underlineRange(lineno, start+offset, end-start) - - for line in errors.splitlines(): - match = re.match(r'(?P.+?) at .+? line (?P\d+)(, near "(?P.+?)")?', line) - - if match: - error, line = match.group('error'), match.group('line') - lineno = int(line) - 1 - - near = match.group('near') - if near: - error = '%s, near "%s"' % (error, near) - underlineRegex(lineno, '(?P%s)' % near) - - lines.add(lineno) - addMessage(lineno, error) - - return underline, lines, errorMessages, True diff --git a/sublimelint/sublimelint/modules/php.py b/sublimelint/sublimelint/modules/php.py deleted file mode 100644 index 22734bd..0000000 --- a/sublimelint/sublimelint/modules/php.py +++ /dev/null @@ -1,46 +0,0 @@ -# php.py - sublimelint package for checking php files - -import subprocess, os - -def check(codeString, filename): - info = None - if os.name == 'nt': - info = subprocess.STARTUPINFO() - info.dwFlags |= subprocess.STARTF_USESHOWWINDOW - info.wShowWindow = subprocess.SW_HIDE - - process = subprocess.Popen(('php', '-l', '-d display_errors=On'), stdin=subprocess.PIPE, stdout=subprocess.PIPE, startupinfo=info) - result = process.communicate(codeString)[0] - - return result - -# start sublimelint php plugin -import re -__all__ = ['run', 'language'] -language = 'PHP' - -def run(code, view, filename='untitled'): - errors = check(code, filename) - - lines = set() - underline = [] # leave this here for compatibility with original plugin - - errorMessages = {} - def addMessage(lineno, message): - message = str(message) - if lineno in errorMessages: - errorMessages[lineno].append(message) - else: - errorMessages[lineno] = [message] - - for line in errors.splitlines(): - match = re.match(r'^Parse error:\s*syntax error,\s*(?P.+?)\s+in\s+.+?\s*line\s+(?P\d+)', line) - - if match: - error, line = match.group('error'), match.group('line') - - lineno = int(line) - 1 - lines.add(lineno) - addMessage(lineno, error) - - return underline, lines, errorMessages, True diff --git a/sublimelint/sublimelint/modules/python.py b/sublimelint/sublimelint/modules/python.py deleted file mode 100644 index cbacc46..0000000 --- a/sublimelint/sublimelint/modules/python.py +++ /dev/null @@ -1,888 +0,0 @@ -# python.py - Lint checking for Python - given filename and contents of the code: -# It provides a list of line numbers to outline and offsets to highlight. -# -# This specific module is a derivative of PyFlakes and part of the SublimeLint project. -# SublimeLint is (c) 2011 Ryan Hileman and licensed under the MIT license. -# URL: http://bochs.info/ -# -# The original copyright notices for this file/project follows: -# -# (c) 2005-2008 Divmod, Inc. -# See LICENSE file for details -# -# The LICENSE file is as follows: -# -# Copyright (c) 2005 Divmod, Inc., http://www.divmod.com/ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -# todo: -# * fix regex for variable names inside strings (quotes) - -import sublime - -import __builtin__ -import os.path -import compiler -from compiler import ast - -class messages: - class Message(object): - message = '' - message_args = () - def __init__(self, filename, lineno): - self.filename = filename - self.lineno = lineno - def __str__(self): - return self.message % self.message_args - - - class UnusedImport(Message): - message = '%r imported but unused' - def __init__(self, filename, lineno, name): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.message_args = (name,) - - - class RedefinedWhileUnused(Message): - message = 'redefinition of unused %r from line %r' - def __init__(self, filename, lineno, name, orig_lineno): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.orig_lineno = orig_lineno - self.message_args = (name, orig_lineno) - - - class ImportShadowedByLoopVar(Message): - message = 'import %r from line %r shadowed by loop variable' - def __init__(self, filename, lineno, name, orig_lineno): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.orig_lineno = orig_lineno - self.message_args = (name, orig_lineno) - - - class ImportStarUsed(Message): - message = "'from %s import *' used; unable to detect undefined names" - def __init__(self, filename, lineno, modname): - messages.Message.__init__(self, filename, lineno) - self.modname = modname - self.message_args = (modname,) - - - class UndefinedName(Message): - message = 'undefined name %r' - def __init__(self, filename, lineno, name): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.message_args = (name,) - - - - class UndefinedExport(Message): - message = 'undefined name %r in __all__' - def __init__(self, filename, lineno, name): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.message_args = (name,) - - - - class UndefinedLocal(Message): - message = "local variable %r (defined in enclosing scope on line %r) referenced before assignment" - def __init__(self, filename, lineno, name, orig_lineno): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.orig_lineno = orig_lineno - self.message_args = (name, orig_lineno) - - - class DuplicateArgument(Message): - message = 'duplicate argument %r in function definition' - def __init__(self, filename, lineno, name): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.message_args = (name,) - - - class RedefinedFunction(Message): - message = 'redefinition of function %r from line %r' - def __init__(self, filename, lineno, name, orig_lineno): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.orig_lineno = orig_lineno - self.message_args = (name, orig_lineno) - - - class LateFutureImport(Message): - message = 'future import(s) %r after other statements' - def __init__(self, filename, lineno, names): - messages.Message.__init__(self, filename, lineno) - self.names = names - self.message_args = (names,) - - - class UnusedVariable(Message): - """ - Indicates that a variable has been explicity assigned to but not actually - used. - """ - - message = 'local variable %r is assigned to but never used' - def __init__(self, filename, lineno, name): - messages.Message.__init__(self, filename, lineno) - self.name = name - self.message_args = (name,) - -class Binding(object): - """ - Represents the binding of a value to a name. - - The checker uses this to keep track of which names have been bound and - which names have not. See L{Assignment} for a special type of binding that - is checked with stricter rules. - - @ivar used: pair of (L{Scope}, line-number) indicating the scope and - line number that this binding was last used - """ - - def __init__(self, name, source): - self.name = name - self.source = source - self.used = False - - - def __str__(self): - return self.name - - - def __repr__(self): - return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__, - self.name, - self.source.lineno, - id(self)) - -class UnBinding(Binding): - '''Created by the 'del' operator.''' - - - -class Importation(Binding): - """ - A binding created by an import statement. - - @ivar fullName: The complete name given to the import statement, - possibly including multiple dotted components. - @type fullName: C{str} - """ - def __init__(self, name, source): - self.fullName = name - name = name.split('.')[0] - super(Importation, self).__init__(name, source) - - - -class Argument(Binding): - """ - Represents binding a name as an argument. - """ - - - -class Assignment(Binding): - """ - Represents binding a name with an explicit assignment. - - The checker will raise warnings for any Assignment that isn't used. Also, - the checker does not consider assignments in tuple/list unpacking to be - Assignments, rather it treats them as simple Bindings. - """ - - - -class FunctionDefinition(Binding): - pass - - - -class ExportBinding(Binding): - """ - A binding created by an C{__all__} assignment. If the names in the list - can be determined statically, they will be treated as names for export and - additional checking applied to them. - - The only C{__all__} assignment that can be recognized is one which takes - the value of a literal list containing literal strings. For example:: - - __all__ = ["foo", "bar"] - - Names which are imported and not otherwise used but appear in the value of - C{__all__} will not have an unused import warning reported for them. - """ - def names(self): - """ - Return a list of the names referenced by this binding. - """ - names = [] - if isinstance(self.source, ast.List): - for node in self.source.nodes: - if isinstance(node, ast.Const): - names.append(node.value) - return names - - - -class Scope(dict): - importStarred = False # set to True when import * is found - - - def __repr__(self): - return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self)) - - - def __init__(self): - super(Scope, self).__init__() - - - -class ClassScope(Scope): - pass - - - -class FunctionScope(Scope): - """ - I represent a name scope for a function. - - @ivar globals: Names declared 'global' in this function. - """ - def __init__(self): - super(FunctionScope, self).__init__() - self.globals = {} - - - -class ModuleScope(Scope): - pass - - -# Globally defined names which are not attributes of the __builtin__ module. -_MAGIC_GLOBALS = ['__file__', '__builtins__'] - - - -class Checker(object): - """ - I check the cleanliness and sanity of Python code. - - @ivar _deferredFunctions: Tracking list used by L{deferFunction}. Elements - of the list are two-tuples. The first element is the callable passed - to L{deferFunction}. The second element is a copy of the scope stack - at the time L{deferFunction} was called. - - @ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for - callables which are deferred assignment checks. - """ - - nodeDepth = 0 - traceTree = False - - def __init__(self, tree, filename='(none)'): - self._deferredFunctions = [] - self._deferredAssignments = [] - self.dead_scopes = [] - self.messages = [] - self.filename = filename - self.scopeStack = [ModuleScope()] - self.futuresAllowed = True - self.handleChildren(tree) - self._runDeferred(self._deferredFunctions) - # Set _deferredFunctions to None so that deferFunction will fail - # noisily if called after we've run through the deferred functions. - self._deferredFunctions = None - self._runDeferred(self._deferredAssignments) - # Set _deferredAssignments to None so that deferAssignment will fail - # noisly if called after we've run through the deferred assignments. - self._deferredAssignments = None - del self.scopeStack[1:] - self.popScope() - self.check_dead_scopes() - - - def deferFunction(self, callable): - ''' - Schedule a function handler to be called just before completion. - - This is used for handling function bodies, which must be deferred - because code later in the file might modify the global scope. When - `callable` is called, the scope at the time this is called will be - restored, however it will contain any new bindings added to it. - ''' - self._deferredFunctions.append((callable, self.scopeStack[:])) - - - def deferAssignment(self, callable): - """ - Schedule an assignment handler to be called just after deferred - function handlers. - """ - self._deferredAssignments.append((callable, self.scopeStack[:])) - - - def _runDeferred(self, deferred): - """ - Run the callables in C{deferred} using their associated scope stack. - """ - for handler, scope in deferred: - self.scopeStack = scope - handler() - - - def scope(self): - return self.scopeStack[-1] - scope = property(scope) - - def popScope(self): - self.dead_scopes.append(self.scopeStack.pop()) - - - def check_dead_scopes(self): - """ - Look at scopes which have been fully examined and report names in them - which were imported but unused. - """ - for scope in self.dead_scopes: - export = isinstance(scope.get('__all__'), ExportBinding) - if export: - all = scope['__all__'].names() - if os.path.split(self.filename)[1] != '__init__.py': - # Look for possible mistakes in the export list - undefined = set(all) - set(scope) - for name in undefined: - self.report( - messages.UndefinedExport, - scope['__all__'].source.lineno, - name) - else: - all = [] - - # Look for imported names that aren't used. - for importation in scope.itervalues(): - if isinstance(importation, Importation): - if not importation.used and importation.name not in all: - self.report( - messages.UnusedImport, - importation.source.lineno, - importation.name) - - - def pushFunctionScope(self): - self.scopeStack.append(FunctionScope()) - - def pushClassScope(self): - self.scopeStack.append(ClassScope()) - - def report(self, messageClass, *args, **kwargs): - self.messages.append(messageClass(self.filename, *args, **kwargs)) - - def handleChildren(self, tree): - for node in tree.getChildNodes(): - self.handleNode(node, tree) - - def handleNode(self, node, parent): - node.parent = parent - if self.traceTree: - print ' ' * self.nodeDepth + node.__class__.__name__ - self.nodeDepth += 1 - nodeType = node.__class__.__name__.upper() - if nodeType not in ('STMT', 'FROM'): - self.futuresAllowed = False - try: - handler = getattr(self, nodeType) - handler(node) - finally: - self.nodeDepth -= 1 - if self.traceTree: - print ' ' * self.nodeDepth + 'end ' + node.__class__.__name__ - - def ignore(self, node): - pass - - STMT = PRINT = PRINTNL = TUPLE = LIST = ASSTUPLE = ASSATTR = \ - ASSLIST = GETATTR = SLICE = SLICEOBJ = IF = CALLFUNC = DISCARD = \ - RETURN = ADD = MOD = SUB = NOT = UNARYSUB = INVERT = ASSERT = COMPARE = \ - SUBSCRIPT = AND = OR = TRYEXCEPT = RAISE = YIELD = DICT = LEFTSHIFT = \ - RIGHTSHIFT = KEYWORD = TRYFINALLY = WHILE = EXEC = MUL = DIV = POWER = \ - FLOORDIV = BITAND = BITOR = BITXOR = LISTCOMPFOR = LISTCOMPIF = \ - AUGASSIGN = BACKQUOTE = UNARYADD = GENEXPR = GENEXPRFOR = GENEXPRIF = \ - IFEXP = handleChildren - - CONST = PASS = CONTINUE = BREAK = ELLIPSIS = ignore - - def addBinding(self, lineno, value, reportRedef=True): - '''Called when a binding is altered. - - - `lineno` is the line of the statement responsible for the change - - `value` is the optional new value, a Binding instance, associated - with the binding; if None, the binding is deleted if it exists. - - if `reportRedef` is True (default), rebinding while unused will be - reported. - ''' - if (isinstance(self.scope.get(value.name), FunctionDefinition) - and isinstance(value, FunctionDefinition)): - self.report(messages.RedefinedFunction, - lineno, value.name, self.scope[value.name].source.lineno) - - if not isinstance(self.scope, ClassScope): - for scope in self.scopeStack[::-1]: - existing = scope.get(value.name) - if (isinstance(existing, Importation) - and not existing.used - and (not isinstance(value, Importation) or value.fullName == existing.fullName) - and reportRedef): - - self.report(messages.RedefinedWhileUnused, - lineno, value.name, scope[value.name].source.lineno) - - if isinstance(value, UnBinding): - try: - del self.scope[value.name] - except KeyError: - self.report(messages.UndefinedName, lineno, value.name) - else: - self.scope[value.name] = value - - - def WITH(self, node): - """ - Handle C{with} by checking the target of the statement (which can be an - identifier, a list or tuple of targets, an attribute, etc) for - undefined names and defining any it adds to the scope and by continuing - to process the suite within the statement. - """ - # Check the "foo" part of a "with foo as bar" statement. Do this no - # matter what, since there's always a "foo" part. - self.handleNode(node.expr, node) - - if node.vars is not None: - self.handleNode(node.vars, node) - - self.handleChildren(node.body) - - - def GLOBAL(self, node): - """ - Keep track of globals declarations. - """ - if isinstance(self.scope, FunctionScope): - self.scope.globals.update(dict.fromkeys(node.names)) - - def LISTCOMP(self, node): - for qual in node.quals: - self.handleNode(qual, node) - self.handleNode(node.expr, node) - - GENEXPRINNER = LISTCOMP - - def FOR(self, node): - """ - Process bindings for loop variables. - """ - vars = [] - def collectLoopVars(n): - if hasattr(n, 'name'): - vars.append(n.name) - else: - for c in n.getChildNodes(): - collectLoopVars(c) - - collectLoopVars(node.assign) - for varn in vars: - if (isinstance(self.scope.get(varn), Importation) - # unused ones will get an unused import warning - and self.scope[varn].used): - self.report(messages.ImportShadowedByLoopVar, - node.lineno, varn, self.scope[varn].source.lineno) - - self.handleChildren(node) - - def NAME(self, node): - """ - Locate the name in locals / function / globals scopes. - """ - # try local scope - importStarred = self.scope.importStarred - try: - self.scope[node.name].used = (self.scope, node.lineno) - except KeyError: - pass - else: - return - - # try enclosing function scopes - - for scope in self.scopeStack[-2:0:-1]: - importStarred = importStarred or scope.importStarred - if not isinstance(scope, FunctionScope): - continue - try: - scope[node.name].used = (self.scope, node.lineno) - except KeyError: - pass - else: - return - - # try global scope - - importStarred = importStarred or self.scopeStack[0].importStarred - try: - self.scopeStack[0][node.name].used = (self.scope, node.lineno) - except KeyError: - if ((not hasattr(__builtin__, node.name)) - and node.name not in _MAGIC_GLOBALS - and not importStarred): - if (os.path.basename(self.filename) == '__init__.py' and - node.name == '__path__'): - # the special name __path__ is valid only in packages - pass - else: - self.report(messages.UndefinedName, node.lineno, node.name) - - - def FUNCTION(self, node): - if getattr(node, "decorators", None) is not None: - self.handleChildren(node.decorators) - self.addBinding(node.lineno, FunctionDefinition(node.name, node)) - self.LAMBDA(node) - - def LAMBDA(self, node): - for default in node.defaults: - self.handleNode(default, node) - - def runFunction(): - args = [] - - def addArgs(arglist): - for arg in arglist: - if isinstance(arg, tuple): - addArgs(arg) - else: - if arg in args: - self.report(messages.DuplicateArgument, node.lineno, arg) - args.append(arg) - - self.pushFunctionScope() - addArgs(node.argnames) - for name in args: - self.addBinding(node.lineno, Argument(name, node), reportRedef=False) - self.handleNode(node.code, node) - def checkUnusedAssignments(): - """ - Check to see if any assignments have not been used. - """ - for name, binding in self.scope.iteritems(): - if (not binding.used and not name in self.scope.globals - and isinstance(binding, Assignment)): - self.report(messages.UnusedVariable, - binding.source.lineno, name) - self.deferAssignment(checkUnusedAssignments) - self.popScope() - - self.deferFunction(runFunction) - - - def CLASS(self, node): - """ - Check names used in a class definition, including its decorators, base - classes, and the body of its definition. Additionally, add its name to - the current scope. - """ - if getattr(node, "decorators", None) is not None: - self.handleChildren(node.decorators) - for baseNode in node.bases: - self.handleNode(baseNode, node) - self.addBinding(node.lineno, Binding(node.name, node)) - self.pushClassScope() - self.handleChildren(node.code) - self.popScope() - - - def ASSNAME(self, node): - if node.flags == 'OP_DELETE': - if isinstance(self.scope, FunctionScope) and node.name in self.scope.globals: - del self.scope.globals[node.name] - else: - self.addBinding(node.lineno, UnBinding(node.name, node)) - else: - # if the name hasn't already been defined in the current scope - if isinstance(self.scope, FunctionScope) and node.name not in self.scope: - # for each function or module scope above us - for scope in self.scopeStack[:-1]: - if not isinstance(scope, (FunctionScope, ModuleScope)): - continue - # if the name was defined in that scope, and the name has - # been accessed already in the current scope, and hasn't - # been declared global - if (node.name in scope - and scope[node.name].used - and scope[node.name].used[0] is self.scope - and node.name not in self.scope.globals): - # then it's probably a mistake - self.report(messages.UndefinedLocal, - scope[node.name].used[1], - node.name, - scope[node.name].source.lineno) - break - - if isinstance(node.parent, - (ast.For, ast.ListCompFor, ast.GenExprFor, - ast.AssTuple, ast.AssList)): - binding = Binding(node.name, node) - elif (node.name == '__all__' and - isinstance(self.scope, ModuleScope) and - isinstance(node.parent, ast.Assign)): - binding = ExportBinding(node.name, node.parent.expr) - else: - binding = Assignment(node.name, node) - if node.name in self.scope: - binding.used = self.scope[node.name].used - self.addBinding(node.lineno, binding) - - def ASSIGN(self, node): - self.handleNode(node.expr, node) - for subnode in node.nodes[::-1]: - self.handleNode(subnode, node) - - def IMPORT(self, node): - for name, alias in node.names: - name = alias or name - importation = Importation(name, node) - self.addBinding(node.lineno, importation) - - def FROM(self, node): - if node.modname == '__future__': - if not self.futuresAllowed: - self.report(messages.LateFutureImport, node.lineno, [n[0] for n in node.names]) - else: - self.futuresAllowed = False - - for name, alias in node.names: - if name == '*': - self.scope.importStarred = True - self.report(messages.ImportStarUsed, node.lineno, node.modname) - continue - name = alias or name - importation = Importation(name, node) - if node.modname == '__future__': - importation.used = (self.scope, node.lineno) - self.addBinding(node.lineno, importation) - -class OffsetError(messages.Message): - message = '%r at offset %r' - def __init__(self, filename, lineno, text, offset): - messages.Message.__init__(self, filename, lineno) - self.offset = offset - self.message_args = (text, offset) - -class PythonError(messages.Message): - message = '%r' - def __init__(self, filename, lineno, text): - messages.Message.__init__(self, filename, lineno) - self.message_args = (text,) - -def check(codeString, filename): - codeString = codeString.rstrip() - try: - try: - compile(codeString, filename, "exec") - except MemoryError: - # Python 2.4 will raise MemoryError if the source can't be - # decoded. - if sys.version_info[:2] == (2, 4): - raise SyntaxError(None) - raise - except (SyntaxError, IndentationError), value: - # print traceback.format_exc() # helps debug new cases - msg = value.args[0] - - lineno, offset, text = value.lineno, value.offset, value.text - - # If there's an encoding problem with the file, the text is None. - if text is None: - # Avoid using msg, since for the only known case, it contains a - # bogus message that claims the encoding the file declared was - # unknown. - if msg.startswith('duplicate argument'): - arg = msg.split('duplicate argument ',1)[1].split(' ',1)[0].strip('\'"') - error = messages.DuplicateArgument(filename, lineno, arg) - else: - error = PythonError(filename, lineno, msg) - else: - line = text.splitlines()[-1] - - if offset is not None: - offset = offset - (len(text) - len(line)) - - if offset is not None: - error = OffsetError(filename, lineno, msg, offset) - else: - error = PythonError(filename, lineno, msg) - - return [error] - except ValueError, e: - return [PythonError(filename, 0, e.args[0])] - else: - # Okay, it's syntactically valid. Now parse it into an ast and check - # it. - tree = compiler.parse(codeString) - w = Checker(tree, filename) - w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno)) - return w.messages - -# end pyflakes -# start sublimelint python plugin - -import sys, re -__all__ = ['run', 'language'] -language = 'Python' - -def run(code, view, filename='untitled'): - stripped_lines = [] - good_lines = [] - lines = code.split('\n') - for i in xrange(len(lines)): - line = lines[i] - if not line.strip() or line.strip().startswith('#'): - stripped_lines.append(i) - else: - good_lines.append(line) - - text = '\n'.join(good_lines) - errors = check(text, filename) - - lines = set() - underline = [] - - def underlineRange(lineno, position, length=1): - line = view.full_line(view.text_point(lineno, 0)) - position += line.begin() - - for i in xrange(length): - underline.append(sublime.Region(position + i)) - - def underlineRegex(lineno, regex, wordmatch=None, linematch=None): - lines.add(lineno) - offset = 0 - - line = view.full_line(view.text_point(lineno, 0)) - lineText = view.substr(line) - if linematch: - match = re.match(linematch, lineText) - if match: - lineText = match.group('match') - offset = match.start('match') - else: - return - - iters = re.finditer(regex, lineText) - results = [(result.start('underline'), result.end('underline')) for result in iters if - not wordmatch or result.group('underline') == wordmatch] - - for start, end in results: - underlineRange(lineno, start+offset, end-start) - - def underlineWord(lineno, word): - regex = r'((and|or|not|if|elif|while|in)\s+|[+\-*^%%<>=\(\{])*\s*(?P[\w\.]*%s[\w]*)' % (word) - underlineRegex(lineno, regex, word) - - def underlineImport(lineno, word): - linematch = '(from\s+[\w_\.]+\s+)?import\s+(?P[^#;]+)' - regex = '(^|\s+|,\s*|as\s+)(?P[\w]*%s[\w]*)' % word - underlineRegex(lineno, regex, word, linematch) - - def underlineForVar(lineno, word): - regex = 'for\s+(?P[\w]*%s[\w*])' % word - underlineRegex(lineno, regex, word) - - def underlineDuplicateArgument(lineno, word): - regex = 'def [\w_]+\(.*?(?P[\w]*%s[\w]*)' % word - underlineRegex(lineno, regex, word) - - errorMessages = {} - def addMessage(lineno, message): - message = str(message) - if lineno in errorMessages: - errorMessages[lineno].append(message) - else: - errorMessages[lineno] = [message] - - for error in errors: - error.lineno -= 1 - for i in stripped_lines: - if error.lineno >= i: - error.lineno += 1 - - lines.add(error.lineno) - addMessage(error.lineno, error) - if isinstance(error, OffsetError): - underlineRange(error.lineno, error.offset) - - elif isinstance(error, PythonError): - pass - - elif isinstance(error, messages.UnusedImport): - underlineImport(error.lineno, error.name) - - elif isinstance(error, messages.RedefinedWhileUnused): - underlineWord(error.lineno, error.name) - - elif isinstance(error, messages.ImportShadowedByLoopVar): - underlineForVar(error.lineno, error.name) - - elif isinstance(error, messages.ImportStarUsed): - underlineImport(error.lineno, '\*') - - elif isinstance(error, messages.UndefinedName): - underlineWord(error.lineno, error.name) - - elif isinstance(error, messages.UndefinedExport): - underlineWord(error.lineno, error.name) - - elif isinstance(error, messages.UndefinedLocal): - underlineWord(error.lineno, error.name) - - elif isinstance(error, messages.DuplicateArgument): - underlineDuplicateArgument(error.lineno, error.name) - - elif isinstance(error, messages.RedefinedFunction): - underlineWord(error.lineno, error.name) - - elif isinstance(error, messages.LateFutureImport): - pass - - elif isinstance(error, messages.UnusedVariable): - underlineWord(error.lineno, error.name) - - else: - print 'Oops, we missed an error type!' - - return underline, lines, errorMessages, True diff --git a/sublimelint/sublimelint/modules/ruby.py b/sublimelint/sublimelint/modules/ruby.py deleted file mode 100644 index d60297b..0000000 --- a/sublimelint/sublimelint/modules/ruby.py +++ /dev/null @@ -1,55 +0,0 @@ -# ruby.py - sublimelint package for checking ruby files - -import subprocess, os - -def check(codeString, filename): - info = None - if os.name == 'nt': - info = subprocess.STARTUPINFO() - info.dwFlags |= subprocess.STARTF_USESHOWWINDOW - info.wShowWindow = subprocess.SW_HIDE - - process = subprocess.Popen(('ruby', '-wc'), - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - startupinfo=info) - result = process.communicate(codeString)[0] - - return result - -# start sublimelint Ruby plugin -import re -__all__ = ['run', 'language'] -language = 'Ruby' -description =\ -'''* view.run_command("lint", "Ruby") - Turns background linter off and runs the default Ruby linter - (ruby -c, assumed to be on $PATH) on current view. -''' - -def run(code, view, filename='untitled'): - errors = check(code, filename) - - lines = set() - underline = [] # leave this here for compatibility with original plugin - - errorMessages = {} - def addMessage(lineno, message): - message = str(message) - if lineno in errorMessages: - errorMessages[lineno].append(message) - else: - errorMessages[lineno] = [message] - - for line in errors.splitlines(): - match = re.match(r'^.+:(?P\d+):\s+(?P.+)', line) - - if match: - error, line = match.group('error'), match.group('line') - - lineno = int(line) - 1 - lines.add(lineno) - addMessage(lineno, error) - - return underline, lines, errorMessages, True diff --git a/sublimelint/sublimelint_plugin.py b/sublimelint/sublimelint_plugin.py deleted file mode 100644 index 4438135..0000000 --- a/sublimelint/sublimelint_plugin.py +++ /dev/null @@ -1,191 +0,0 @@ -import sublime, sublime_plugin -import os, sys, glob - -## todo: -# * fix lag (was partially caused by multiple worker threads - evaluate if it's still an issue) - -## language module loading - -# mapping of language name to language module -languages = {} - -# import config -basepath = 'sublimelint/modules' -modpath = basepath.replace('/', '.') -ignore = '__init__', -basedir = os.getcwd() - -def load_module(name): - fullmod = '%s.%s' % (modpath, name) - - # make sure the path didn't change on us (this is needed for submodule reload) - pushd = os.getcwd() - os.chdir(basedir) - - __import__(fullmod) - - # this following line does two things: - # first, we get the actual module from sys.modules, not the base mod returned by __import__ - # second, we get an updated version with reload() so module development is easier - # (save sublimelint_plugin.py to make sublime text reload language submodules) - mod = sys.modules[fullmod] = reload(sys.modules[fullmod]) - - # update module's __file__ to absolute path so we can reload it if saved with sublime text - mod.__file__ = os.path.abspath(mod.__file__).rstrip('co') - - try: - language = mod.language - languages[language] = mod - except AttributeError: - print 'SublimeLint: Error loading %s - no language specified' % modf - except: - print 'SublimeLint: General error importing %s' % modf - - os.chdir(pushd) - -def reload_module(module): - fullmod = module.__name__ - if not fullmod.startswith(modpath): - return - - name = fullmod.replace(modpath+'.', '', 1) - load_module(name) - -for modf in glob.glob('%s/*.py' % basepath): - base, name = os.path.split(modf) - name = name.split('.', 1)[0] - if name in ignore: continue - - load_module(name) - -## bulk of the code - -# TODO: check to see if the types specified after drawType in the codestill work and replace as necessary -drawType = 4 | 32 # from before ST2 had sublime.DRAW_* - -global lineMessages -lineMessages = {} - -def run(module, view): - global lineMessages - vid = view.id() - - text = view.substr(sublime.Region(0, view.size())).encode('utf-8') - - if view.file_name(): - filename = os.path.split(view.file_name())[-1] - else: - filename = 'untitled' - - underline, lines, errorMessages, clearOutlines = module.run(text, view, filename) - lineMessages[vid] = errorMessages - - view.erase_regions('lint-syntax') - view.erase_regions('lint-syntax-underline') - view.erase_regions('lint-underline') - - if clearOutlines: - view.erase_regions('lint-outlines') - - if underline: - view.add_regions('lint-underline', underline, 'keyword', drawType)#sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_OUTLINED) - - if lines: - outlines = [view.full_line(view.text_point(lineno, 0)) for lineno in lines] - view.add_regions('lint-outlines', outlines, 'keyword', drawType)#sublime.DRAW_EMPTY_AS_OVERWRITE | sublime.DRAW_OUTLINED) - - -def validate(view): - for language in languages: - if language in view.settings().get("syntax"): - run(languages[language], view) - break - -import time, thread -queue = {} -lookup = {} - -def validate_runner(): # this threaded runner keeps it from slowing down UI while you type - while True: - time.sleep(0.5) - for vid in dict(queue): - if queue[vid] == 0: - v = lookup[vid] - def _view(): - try: - validate(v) - except RuntimeError, excp: - print excp - sublime.set_timeout(_view, 100) - try: del queue[vid] - except: pass - try: del lookup[vid] - except: pass - else: - queue[vid] = 0 - -def validate_hit(view): - for language in languages: - if language in view.settings().get("syntax"): - break - else: - view.erase_regions('lint-syntax') - view.erase_regions('lint-syntax-underline') - view.erase_regions('lint-underline') - view.erase_regions('lint-outlines') - return - - vid = view.id() - lookup[vid] = view - queue[vid] = 1 - -# only start the thread once - otherwise the plugin will get laggy when saving it often -if not 'already' in globals(): - already = True - thread.start_new_thread(validate_runner, ()) - -class pyflakes(sublime_plugin.EventListener): - def __init__(self, *args, **kwargs): - sublime_plugin.EventListener.__init__(self, *args, **kwargs) - self.lastCount = {} - - def on_modified(self, view): - validate_hit(view) - return - - # alternate method which works alright when we don't have threads/set_timeout - # from when I ported to early X beta :P - text = view.substr(sublime.Region(0, view.size())).encode('utf-8') - count = text.count('\n') - if count > 500: return - bid = view.buffer_id() - - if bid in self.lastCount: - if self.lastCount[bid] != count: - validate(view) - - self.lastCount[bid] = count - - def on_load(self, view): - validate(view) - - def on_post_save(self, view): - # this will reload submodules if they are saved with sublime text - for name, module in languages.items(): - if module.__file__ == view.file_name(): - print 'Sublime Lint - Reloading language:', module.language - reload_module(module) - break - - validate_hit(view) - - def on_selection_modified(self, view): - vid = view.id() - lineno = view.rowcol(view.sel()[0].end())[0] - if vid in lineMessages and lineno in lineMessages[vid]: - try: # workaround for issue #18 - view.set_status('pyflakes', '; '.join(lineMessages[vid][lineno])) - except: - view.erase_status('pyflakes') - else: - view.erase_status('pyflakes')