├── Packages
├── SourcePawn
│ ├── .extracted-sublime-package
│ ├── .gitattributes
│ ├── .gitignore
│ ├── CFG.sublime-settings
│ ├── CFG.sublime-syntax
│ ├── COPYING
│ ├── Comments.tmPreferences
│ ├── CompletionRules.tmPreferences
│ ├── Main.sublime-menu
│ ├── README.md
│ ├── SPCompletions.py
│ ├── SourcePawn Completions.sublime-settings
│ ├── SourcePawn.sublime-build.example
│ ├── SourcePawn.sublime-completions
│ ├── SourcePawn.sublime-settings
│ ├── SourcePawn.sublime-syntax
│ ├── SourcePawnSnippets
│ │ ├── AmbientSHook.sublime-snippet
│ │ ├── Case.sublime-snippet
│ │ ├── CommandListener.sublime-snippet
│ │ ├── ConCmd.sublime-snippet
│ │ ├── ConVarQueryFinished01.sublime-snippet
│ │ ├── ConVarQueryFinished02.sublime-snippet
│ │ ├── ConvarChanged.sublime-snippet
│ │ ├── CookieMenuHandler.sublime-snippet
│ │ ├── DHookCallback01.sublime-snippet
│ │ ├── DHookCallback02.sublime-snippet
│ │ ├── DHookCallback03.sublime-snippet
│ │ ├── DHookCallback04.sublime-snippet
│ │ ├── DHookCallback05.sublime-snippet
│ │ ├── DHookCallback06.sublime-snippet
│ │ ├── DHookCallback07.sublime-snippet
│ │ ├── DHookCallback08.sublime-snippet
│ │ ├── DHookCallback09.sublime-snippet
│ │ ├── DHookCallback10.sublime-snippet
│ │ ├── DHookCallback11.sublime-snippet
│ │ ├── DHookCallback12.sublime-snippet
│ │ ├── DHookRemovalCB.sublime-snippet
│ │ ├── Default.sublime-snippet
│ │ ├── Do.sublime-snippet
│ │ ├── Else.sublime-snippet
│ │ ├── EntityOutput01.sublime-snippet
│ │ ├── EntityOutput02.sublime-snippet
│ │ ├── EventHook01.sublime-snippet
│ │ ├── EventHook02.sublime-snippet
│ │ ├── For.sublime-snippet
│ │ ├── GameLogHook.sublime-snippet
│ │ ├── If.sublime-snippet
│ │ ├── Include.sublime-snippet
│ │ ├── ListenCB01.sublime-snippet
│ │ ├── ListenCB02.sublime-snippet
│ │ ├── MenuHandler.sublime-snippet
│ │ ├── Methodmap.sublime-snippet
│ │ ├── MsgHook01.sublime-snippet
│ │ ├── MsgHook02.sublime-snippet
│ │ ├── MsgPostHook.sublime-snippet
│ │ ├── MultiTargetFilter01.sublime-snippet
│ │ ├── MultiTargetFilter02.sublime-snippet
│ │ ├── MultiTargetFilter03.sublime-snippet
│ │ ├── MultiTargetFilter04.sublime-snippet
│ │ ├── MyInfo.sublime-snippet
│ │ ├── NativeCall01.sublime-snippet
│ │ ├── NativeCall02.sublime-snippet
│ │ ├── NewPlugin.sublime-snippet
│ │ ├── NormalSHook.sublime-snippet
│ │ ├── RequestFrameCallback01.sublime-snippet
│ │ ├── RequestFrameCallback02.sublime-snippet
│ │ ├── SDKHookCB01.sublime-snippet
│ │ ├── SDKHookCB02.sublime-snippet
│ │ ├── SDKHookCB03.sublime-snippet
│ │ ├── SDKHookCB04.sublime-snippet
│ │ ├── SDKHookCB05.sublime-snippet
│ │ ├── SDKHookCB06.sublime-snippet
│ │ ├── SDKHookCB07.sublime-snippet
│ │ ├── SDKHookCB08.sublime-snippet
│ │ ├── SDKHookCB09.sublime-snippet
│ │ ├── SDKHookCB10.sublime-snippet
│ │ ├── SDKHookCB11.sublime-snippet
│ │ ├── SDKHookCB12.sublime-snippet
│ │ ├── SDKHookCB13.sublime-snippet
│ │ ├── SDKHookCB14.sublime-snippet
│ │ ├── SDKHookCB15.sublime-snippet
│ │ ├── SDKHookCB16.sublime-snippet
│ │ ├── SDKHookCB17.sublime-snippet
│ │ ├── SDKHookCB18.sublime-snippet
│ │ ├── SDKHookCB19.sublime-snippet
│ │ ├── SDKHookCB20.sublime-snippet
│ │ ├── SDKHookCB21.sublime-snippet
│ │ ├── SDKHookCB22.sublime-snippet
│ │ ├── SDKHookCB23.sublime-snippet
│ │ ├── SDKHookCB24.sublime-snippet
│ │ ├── SMC_EndSection.sublime-snippet
│ │ ├── SMC_KeyValue.sublime-snippet
│ │ ├── SMC_NewSection.sublime-snippet
│ │ ├── SMC_ParseEnd.sublime-snippet
│ │ ├── SMC_ParseStart.sublime-snippet
│ │ ├── SMC_RawLine.sublime-snippet
│ │ ├── SQLConnectCallback.sublime-snippet
│ │ ├── SQLQueryCallback.sublime-snippet
│ │ ├── SQLTCallback.sublime-snippet
│ │ ├── SQLTxnFailure.sublime-snippet
│ │ ├── SQLTxnSuccess.sublime-snippet
│ │ ├── SortFunc1D.sublime-snippet
│ │ ├── SortFunc2D.sublime-snippet
│ │ ├── SortFuncADTArray.sublime-snippet
│ │ ├── SrvCmd.sublime-snippet
│ │ ├── Switch.sublime-snippet
│ │ ├── TEHook.sublime-snippet
│ │ ├── TestPlugin.sublime-snippet
│ │ ├── Timer01.sublime-snippet
│ │ ├── Timer02.sublime-snippet
│ │ ├── TopMenuHandler.sublime-snippet
│ │ ├── TraceEntityEnumerator01.sublime-snippet
│ │ ├── TraceEntityEnumerator02.sublime-snippet
│ │ ├── TraceEntityFilter01.sublime-snippet
│ │ ├── TraceEntityFilter02.sublime-snippet
│ │ ├── Typedef.sublime-snippet
│ │ ├── Typeset.sublime-snippet
│ │ ├── ViewAs.sublime-snippet
│ │ ├── VoteHandler.sublime-snippet
│ │ └── While.sublime-snippet
│ ├── SymbolList.tmPreferences
│ ├── misc
│ │ └── constantcrawler.py
│ ├── notes.txt
│ ├── pathtools
│ │ ├── __init__.py
│ │ ├── path.py
│ │ ├── patterns.py
│ │ └── version.py
│ └── watchdog
│ │ ├── __init__.py
│ │ ├── events.py
│ │ ├── observers
│ │ ├── __init__.py
│ │ ├── api.py
│ │ ├── fsevents.py
│ │ ├── fsevents2.py
│ │ ├── inotify.py
│ │ ├── inotify_buffer.py
│ │ ├── inotify_c.py
│ │ ├── kqueue.py
│ │ ├── polling.py
│ │ ├── read_directory_changes.py
│ │ └── winapi.py
│ │ ├── tricks
│ │ └── __init__.py
│ │ ├── utils
│ │ ├── __init__.py
│ │ ├── bricks.py
│ │ ├── compat.py
│ │ ├── decorators.py
│ │ ├── dirsnapshot.py
│ │ ├── echo.py
│ │ ├── importlib2.py
│ │ ├── platform.py
│ │ ├── unicode_paths.py
│ │ └── win32stat.py
│ │ └── version.py
└── User
│ ├── Preferences.sublime-settings
│ ├── SaucePawn.sublime-color-scheme
│ ├── SourcePawn Completions.sublime-settings
│ └── bh_core.sublime-settings
└── README.md
/Packages/SourcePawn/.extracted-sublime-package:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JoinedSenses/sourcepawn_sublime_stuff/aec6d237c125fa6b38ec3f2b9e062d72457553b9/Packages/SourcePawn/.extracted-sublime-package
--------------------------------------------------------------------------------
/Packages/SourcePawn/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Explicitly declare text files we want to always be normalized and converted
5 | # to native line endings on checkout.
6 | *.sublime-* text
7 | *.*Theme text
8 | *.*Preferences text
9 | *.*Language text
--------------------------------------------------------------------------------
/Packages/SourcePawn/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.cache
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/CFG.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | "extensions":
3 | [
4 | "cfg"
5 | ]
6 | }
--------------------------------------------------------------------------------
/Packages/SourcePawn/CFG.sublime-syntax:
--------------------------------------------------------------------------------
1 | %YAML 1.2
2 | ---
3 | name: Config
4 | file_extensions: [cfg]
5 | scope: source.cfg
6 |
7 | variables:
8 | end_of_line: '(?
2 |
3 |
4 |
5 | name
6 | SourcePawnComments
7 | scope
8 | source.sp
9 | settings
10 |
11 | shellVariables
12 |
13 |
14 | name
15 | TM_COMMENT_START
16 | value
17 | //
18 |
19 |
20 | name
21 | TM_COMMENT_START_2
22 | value
23 | /*
24 |
25 |
26 | name
27 | TM_COMMENT_END_2
28 | value
29 | */
30 |
31 |
32 | name
33 | TM_COMMENT_DISABLE_INDENT
34 | value
35 | yes
36 |
37 |
38 | name
39 | TM_COMMENT_DISABLE_INDENT_2
40 | value
41 | yes
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/CompletionRules.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | scope
5 | source.sp
6 | settings
7 |
8 | cancelCompletion
9 |
10 | ^\s*(#if|#else|#elseif|#endif|#pragma)
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/Main.sublime-menu:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "caption": "Preferences",
4 | "mnemonic": "n",
5 | "id": "preferences",
6 | "children":
7 | [
8 | {
9 | "caption": "Package Settings",
10 | "mnemonic": "P",
11 | "id": "package-settings",
12 | "children":
13 | [
14 | {
15 | "caption": "SourcePawn Completions",
16 | "children":
17 | [
18 | {
19 | "command": "open_file",
20 | "args": {"file": "${packages}/SourcePawn Completions/SourcePawn Completions.sublime-settings"},
21 | "caption": "Settings - Default"
22 | },
23 | {
24 | "command": "open_file",
25 | "args": {"file": "${packages}/User/SourcePawn Completions.sublime-settings"},
26 | "caption": "Settings - User"
27 | },
28 | { "caption": "-" },
29 | {
30 | "command": "open_file",
31 | "args": {"file": "${packages}/SourcePawn Completions/SourcePawn.sublime-build.example"},
32 | "caption": "Build system - Example"
33 | },
34 | {
35 | "command": "open_file",
36 | "args": {"file": "${packages}/User/SourcePawn.sublime-build"},
37 | "caption": "Build system - User"
38 | },
39 | { "caption": "-" }
40 | ]
41 | }
42 | ]
43 | }
44 | ]
45 | }
46 | ]
47 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/README.md:
--------------------------------------------------------------------------------
1 | # SourcePawn Completions for SublimeText 3
2 |
3 | A Sublime Text 4 plugin that dynamically genenerates completions for SourcePawn.
4 |
5 | Based on [sublime-sourcepawn](https://github.com/austinwagner/sublime-sourcepawn).
6 | Includes [watchdog python module](https://https://github.com/gorakhargosh/watchdog)
7 |
8 |
9 |

10 |
11 | ## Installing
12 |
13 | ### Via [package control](https://packagecontrol.io/installation)
14 |
15 | ~~1. Press `Control+Shift+P` or `Cmd+Shift+P` (on Mac)~~
16 | ~~2. Type **Package Control: Install Package**, hit enter.~~
17 | ~~3. Type in **SourcePawn Completions**, hit enter again.~~
18 |
19 | ### Manually
20 |
21 | Clone this repository into a subfolder of your Packages directory:
22 | * Mac OS `~/Library/Application Support/Sublime Text 3/Packages/`
23 | * Windows `%APPDATA%/Sublime Text 3/Packages/`
24 |
25 | ## Configuration
26 | **Note:** All paths must be an absolute. Relative paths are unsupported.
27 |
28 | 1. Open *Sublime Text* -> *Preferences* -> *Package Settings* -> *SourcePawn Completions* -> *Settings - User*.
29 | 2. Add `include_directory` setting with path to your SourceMod include files (`sourcemod/scripting` folder). (You could look for some exmaples in *Settings - Default*)
30 | 3. Save and close file.
31 | 4. Open *Sublime Text* -> *Preferences* -> *Package Settings* -> *SourcePawn Completions* -> *Build settings - Example* and *Build settings - User*
32 | 5. Copy one of `cmd` settings from `SourcePawn.sublime-build.example`, paste it to `SourcePawn.sublime-build` and ajust path to `spcomp`. This allows you to use **Build** feature in SublimeText.
33 | 6. Save and close file.
34 |
35 | ## Usage
36 |
37 | SourcePawn Completions is automatically active on .sp and .inc files. The completion list updates whenever you stop typing for 1 second or when you save the file.
38 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawn Completions.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | // path to sourcemod "scripting/include" folder
3 | // Windows example: // Support for multiple directories. Searches top to bottom until it finds include
4 | // "include_directory": [
5 | // "D:\\sourcemod\\scripting\\include",
6 | // "C:\\another\\sourcemod\\include", // optional
7 | /// "etc . . ." // optional
8 | // ],
9 | // OSX example:
10 | // "include_directory": [
11 | // "/Users/ppalex/sourcemod/scripting/include",
12 | // "/Users/ppalex/some/other/sourcemod/scripting/include", // optional
13 | // "etc . . ." // optional
14 | // ],
15 |
16 | // delay (in seconds) before regenerating auto-completion snippets
17 | "live_refresh_delay": 1.0
18 | }
19 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawn.sublime-build.example:
--------------------------------------------------------------------------------
1 | {
2 | // Copy on of "cmd" examples to "Build settings - User"
3 | // and ajust path to spcomp to make build-system work.
4 |
5 | // For default sourcemod scripting directory :
6 | // "cmd": ["", "-o$file_path/../plugins/$file_name", "$file"],
7 |
8 | // For custom sourcemod scripting directory :
9 | // "cmd": ["", "-i", "-o$file_path/$file_base_name.smx", "$file"],
10 |
11 | // Windows example:
12 | "cmd": ["X:/somefolder/spcomp", "-iX:/somefolder/scripting/include", "-o$file_path/$file_base_name.smx", "$file"],
13 | "cmd": ["X:/game/csgo/addons/sourcemod/scripting/spcomp", "-o$file_path/../plugins/$file_name", "$file"],
14 |
15 | // Linux example:
16 | "cmd": ["/home/User/sm/spcomp", "-i/home/User/sm/include", "-o$file_path/$file_base_name.smx", "$file"],
17 | "cmd": ["/home/User/game/csgo/addons/sourcemod/scripting/spcomp", "-o$file_path/../plugins/$file_name", "$file"],
18 |
19 | // OSX example:
20 | "cmd": ["/Users/ppalex/sourcemod/scripting/spcomp", "-i$file_path/include", "-o$file_path/../plugins/$file_name", "$file"],
21 |
22 | "file_regex": "(.*)\\((\\d+)\\) : ()(.*$)",
23 | "selector": "source.sp"
24 | }
25 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawn.sublime-completions:
--------------------------------------------------------------------------------
1 | {
2 | "scope": "source.sp",
3 | "completions":
4 | [
5 | { "trigger": "view_as", "contents": "view_as<$1>($0)" }
6 | ]
7 | }
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawn.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | "extensions":
3 | [
4 | "sp",
5 | "inc"
6 | ],
7 |
8 | // "word_separators": "./\\()\"':,;<>~!@#$%^&*|+=[]{}`~?",
9 | "smart_indent": true,
10 | "detect_indentation": false,
11 | "tab_size": 4,
12 | "translate_tabs_to_spaces": false,
13 | "draw_indent_guides": false,
14 |
15 | "auto_complete_include_snippets": "true",
16 | "auto_complete_preserve_order":"none",
17 | "auto_complete_selector": "source - comment - string.quoted",
18 | }
19 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/AmbientSHook.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 | __AmbientSHook(char[PLATFORM_MAX_PATH], int&, float&, int&, int&, float[3], int&, float&) : Action
12 |
13 | source.sp - meta.function
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Case.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | case
9 |
10 | source.sp & meta.function & meta.block
11 |
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/CommandListener.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __CommandListener(int, const char[], int) : Action
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/ConCmd.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
8 | __ConCmd(int, int) : Action
9 | source.sp - meta.function
10 |
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/ConVarQueryFinished01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __ConVarQueryFinished(QueryCookie, int, ConVarQueryResult, const char[], const char[]) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/ConVarQueryFinished02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __ConVarQueryFinished(QueryCookie, int, ConVarQueryResult, const char[], const char[], any)) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/ConvarChanged.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | __ConVarChanged(ConVar, const char[], const char[]) : void
8 | source.sp - meta.function
9 |
10 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/CookieMenuHandler.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | __CookieMenuHandler(int, CookieMenuAction, any, char[], int) : void
8 | source.sp - meta.function
9 |
10 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback() : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(int) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback03.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(DHookParam) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback04.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(int, DHookParam) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback05.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(DHookReturn) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback06.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(int, DHookReturn) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback07.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(DHookReturn, DHookParam) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback08.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(int, DHookReturn, DHookParam) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback09.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(Address) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback10.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(Address, DHookParam) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback11.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(Address, DHookReturn) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookCallback12.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __DHookCallback(Address, DHookReturn, DHookParam) : MRESReturn
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/DHookRemovalCB.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __DHookRemovalCB(int) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Default.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | default
9 |
10 | source.sp & meta.function & meta.block
11 |
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Do.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | do
9 |
10 | source.sp & meta.function & meta.block
11 |
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Else.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | else
8 | source.sp & meta.function & meta.block
9 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/EntityOutput01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __EntityOutput(const char[], int, int, float) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/EntityOutput02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __EntityOutput(const char[], int, int, float) : Action
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/EventHook01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | __EventHook(Event, const char[], bool) : void
8 | source.sp - meta.function
9 |
10 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/EventHook02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | __EventHook(Event, const char[], bool) : Action
8 | source.sp - meta.function
9 |
10 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/For.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | for
8 | source.sp & meta.function & meta.block
9 |
10 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/GameLogHook.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __GameLogHook(const char[]) : Action
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/If.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
6 | if
7 | source.sp & meta.function & meta.block
8 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Include.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
48 | __include
49 | source.sp - meta.function
50 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/ListenCB01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __ListenCB(int) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/ListenCB02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __ListenCB(int, const char[]) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MenuHandler.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
57 |
58 | __MenuHandler(Menu, MenuAction, int, int) : int
59 |
60 | source.sp - meta.function
61 |
62 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Methodmap.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 | ($0);
6 | }
7 | }
8 | ]]>
9 | methodmap
10 | source.sp - meta.function
11 |
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MsgHook01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __MsgHook(UserMsg, BfRead, const int[], int, bool, bool) : Action
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MsgHook02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __MsgHook(UserMsg, Protobuf, const int[], int, bool, bool) : Action
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MsgPostHook.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __MsgPostHook(UserMsg, bool) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MultiTargetFilter01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __MultiTargetFilter(const char[], Handle) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MultiTargetFilter02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __MultiTargetFilter(const char[], ArrayList) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MultiTargetFilter03.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __MultiTargetFilter(const char[], Handle, int) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MultiTargetFilter04.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __MultiTargetFilter(const char[], ArrayList, int) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/MyInfo.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
11 | __myinfo
12 | source.sp - meta.function
13 |
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/NativeCall01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __NativeCall(Handle, int) : int
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/NativeCall02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __NativeCall(Handle, int) : any
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/NewPlugin.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | #define PLUGIN_NAME "${1:NewPlugin}"
9 | #define PLUGIN_AUTHOR "${2:}"
10 | #define PLUGIN_DESCRIPTION "${3:}"
11 | #define PLUGIN_VERSION "${4:0.1.0}"
12 | #define PLUGIN_URL "${5:https://alliedmods.net}"
13 |
14 | public Plugin myinfo = {
15 | name = PLUGIN_NAME,
16 | author = PLUGIN_AUTHOR,
17 | description = PLUGIN_DESCRIPTION,
18 | version = PLUGIN_VERSION,
19 | url = PLUGIN_URL
20 | }
21 |
22 | public void OnPluginStart() {
23 | CreateConVar(
24 | "sm_${1/([A-Z])|(\s)/(?1\l$1:)(?2:)/g}_version",
25 | PLUGIN_VERSION,
26 | PLUGIN_DESCRIPTION,
27 | FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD
28 | ).SetString(PLUGIN_VERSION);
29 |
30 | $0
31 | }
32 | ]]>
33 | __newplugin
34 | source.sp - meta.function
35 |
36 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/NormalSHook.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 | __NormalSHook(int[MAXPLAYERS], int&, char[PLATFORM_MAX_PATH], int&, int&, float&, int&, int&, int&, char[PLATFORM_MAX_PATH], int&) : Action
12 |
13 | source.sp - meta.function
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/RequestFrameCallback01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __RequestFrameCallback() : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/RequestFrameCallback02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __RequestFrameCallback(any) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int) : void
9 |
10 | source.sp - meta.function
11 | PreThink/Post PostThink/Post
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int) : Action
11 |
12 | source.sp - meta.function
13 | Spawn Think
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB03.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int) : void
9 |
10 | source.sp - meta.function
11 | GroundEntChanged SpawnPost ThinkPost VPhysicsUpdate/Post
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB04.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int) : Action
11 |
12 | source.sp - meta.function
13 | EndTouch StartTouch Touch Blocked
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB05.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, int) : void
9 |
10 | source.sp - meta.function
11 | EndTouchPost StartTouchPost TouchPost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB06.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int) : Action
11 |
12 | source.sp - meta.function
13 | SetTransmit
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB07.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int) : Action
11 |
12 | source.sp - meta.function
13 | WeaponCanSwitchTo WeaponCanUse WeaponDrop WeaponEquip WeaponSwitch
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB08.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, int) : void
9 |
10 | source.sp - meta.function
11 | WeaponCanSwitchToPost WeaponCanUsePost WeaponDropPost WeaponEquipPost WeaponSwitchPost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB09.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int&) : Action
11 |
12 | source.sp - meta.function
13 | GetMaxHealth
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB10.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int&, int&, float&, int&) : Action
11 |
12 | source.sp - meta.function
13 | OnTakeDamage OnTakeDamageAlive
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB11.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int&, int&, float&, int&, int&, float[3], float[3]) : Action
11 |
12 | source.sp - meta.function
13 | OnTakeDamage OnTakeDamageAlive
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB12.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 | __SDKHookCB(int, int&, int&, float&, int&, int&, float[3], float[3], int) : Action
12 |
13 | source.sp - meta.function
14 | OnTakeDamage OnTakeDamageAlive
15 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB13.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, int, int, float, int) : void
9 |
10 | source.sp - meta.function
11 | OnTakeDamagePost OnTakeDamageAlivePost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB14.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, int, int, float, int, int, const float[3], const float[3]) : void
9 |
10 | source.sp - meta.function
11 | OnTakeDamagePost OnTakeDamageAlivePost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB15.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | __SDKHookCB(int, int, int, float, int, int, const float[3], const float[3], int) : void
10 |
11 | source.sp - meta.function
12 | OnTakeDamagePost OnTakeDamageAlivePost
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB16.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, int, const char[]) : void
9 |
10 | source.sp - meta.function
11 | FireBulletsPost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB17.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int&, int&, float&, int&, int&, int, int) : Action
11 |
12 | source.sp - meta.function
13 | TraceAttack
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB18.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, int, int, float, int, int, int, int) : void
9 |
10 | source.sp - meta.function
11 | TraceAttackPost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB19.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int, int, bool) : bool
11 |
12 | source.sp - meta.function
13 | ShouldCollide
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB20.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, int, int, UseType, float) : Action
11 |
12 | source.sp - meta.function
13 | Use
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB21.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, int, int, UseType, float) : void
9 |
10 | source.sp - meta.function
11 | UsePost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB22.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int) : Action
11 |
12 | source.sp - meta.function
13 | Reload
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB23.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SDKHookCB(int, bool)) : void
9 |
10 | source.sp - meta.function
11 | ReloadPost
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SDKHookCB24.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SDKHookCB(int, bool) : bool
11 |
12 | source.sp - meta.function
13 | CanBeAutobalanced
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SMC_EndSection.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SMC_EndSection(SMCParser) : SMCResult
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SMC_KeyValue.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SMC_KeyValue(SMCParser, const char[], const char[], bool, bool) : SMCResult
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SMC_NewSection.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SMC_NewSection(SMCParser, const char[], bool) : SMCResult
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SMC_ParseEnd.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SMC_ParseEnd(SMCParser, bool, bool) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SMC_ParseStart.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SMC_ParseStart(SMCParser) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SMC_RawLine.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SMC_RawLine(SMCParser, const char[], int) : SMCResult
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SQLConnectCallback.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
11 | __SQLConnectCallback(Database, const char[], any) : void
12 | source.sp - meta.function
13 |
14 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SQLQueryCallback.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
12 | __SQLQueryCallback(Database, DBResultSet, const char[], any) : void
13 | source.sp - meta.function
14 |
15 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SQLTCallback.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | __SQLTCallback(Handle, Handle, const char[], any) : void
9 |
10 | source.sp - meta.function
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SQLTxnFailure.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | __SQLTxnFailure(Database, any, int, const char[], int failIndex, any[]) : void
8 | source.sp - meta.function
9 |
10 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SQLTxnSuccess.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 | __SQLTxnSuccess(Database, any, int, DBResultSet[], any[]) : void
8 | source.sp - meta.function
9 |
10 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SortFunc1D.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SortFunc1D(any, any, const any[], any) : int
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SortFunc2D.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SortFunc2D(any[], any[], const any[][], any) : int
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SortFuncADTArray.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __SortFuncADTArray(int, int, Handle, any) : int
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/SrvCmd.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 | __SrvCmd(int) : Action
10 | source.sp - meta.function
11 |
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Switch.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | switch
9 |
10 | source.sp & meta.function & meta.block
11 |
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/TEHook.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __TEHook(const char[], const int[], int, float) : Action
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/TestPlugin.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | public Plugin myinfo = {
9 | name = "${TM_FILENAME/(.+)\..+/$1/}",
10 | author = "",
11 | description = "",
12 | version = "0.1.0",
13 | url = ""
14 | }
15 |
16 | public void OnPluginStart() {
17 | RegAdminCmd("sm_${1:test}", ${2:cmdTest}, ADMFLAG_ROOT);
18 | }
19 |
20 | public Action $2(int client, int args) {
21 | $0
22 |
23 | return Plugin_Handled;
24 | }
25 | ]]>
26 | __test
27 | source.sp - meta.function
28 |
29 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Timer01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
8 | __Timer(Handle) : Action
9 | source.sp - meta.function
10 |
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Timer02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
8 | __Timer(Handle, any) : Action
9 | source.sp - meta.function
10 |
11 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/TopMenuHandler.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | __TopMenuHandler(TopMenu, TopMenuAction, TopMenuObject, int, char[], int) : void
10 |
11 | source.sp - meta.function
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/TraceEntityEnumerator01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __TraceEntityEnumerator(int) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/TraceEntityEnumerator02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __TraceEntityEnumerator(int, any) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/TraceEntityFilter01.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __TraceEntityFilter(int, int) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/TraceEntityFilter02.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 | __TraceEntityFilter(int, int, any) : bool
11 |
12 | source.sp - meta.function
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Typedef.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
5 | typedef
6 | source.sp - meta.function
7 |
8 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/Typeset.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | typeset
10 |
11 | source.sp - meta.function
12 |
13 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/ViewAs.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 | ($2)
4 | ]]>
5 | view_as
6 | source.sp
7 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/VoteHandler.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | __VoteHandler(Menu, int, int, const int[][], int, const int[][]) : void
10 |
11 | source.sp - meta.function
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SourcePawnSnippets/While.sublime-snippet:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | while
9 |
10 | source.sp & meta.function & meta.block
11 |
12 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/SymbolList.tmPreferences:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | name
5 | Symbol List
6 | scope
7 |
8 | settings
9 |
10 | showInSymbolList
11 | 1
12 | showInIndexedSymbolList
13 | 1
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/misc/constantcrawler.py:
--------------------------------------------------------------------------------
1 | from os import PathLike
2 | from pathlib import PurePath
3 | import os.path
4 | import pathlib
5 | import pyperclip
6 | import re
7 | import sys
8 | from argparse import ArgumentParser
9 | from io import TextIOWrapper
10 | from trieregex import TrieRegEx # https://github.com/ermanh/trieregex
11 |
12 |
13 | argparser = ArgumentParser(description='Crawls through include directories and files to generate a regex trie for matching constants')
14 | argparser.add_argument('--debug', help='Enable debug messages', action='store_true')
15 | argparser.add_argument('--recursive', help='Enable recusive directory crawling', action='store_true')
16 | argparser.add_argument('paths', metavar='Paths', type=str, nargs='+', help='Paths to crawl. Can be directory or file.')
17 | argparser.add_argument_group()
18 |
19 | parsedargs = argparser.parse_args()
20 |
21 |
22 | class Debug:
23 | __enabled = parsedargs.debug
24 |
25 | @staticmethod
26 | def log(value: str) -> None:
27 | if Debug.__enabled: print(value)
28 |
29 |
30 | def main(args: list[str]):
31 | """
32 | Crawls through include directories and files to generate a regex trie for matching constants.
33 | Ignores variables IN_ALL_CAPS since those are already discovered with a basic all-caps regex for the
34 | purpose of syntax highlighting.
35 |
36 | Args:
37 | args (list[str]): List of paths to process
38 | """
39 | if len(args) < 1:
40 | argparser.print_help()
41 | sys.exit(1)
42 |
43 | error: str = ''
44 | for arg in args:
45 | if not os.path.exists(arg):
46 | error += '\n Path not found: {}'.format(arg)
47 | if error:
48 | print('\nErrors detected:{}'.format(error))
49 | sys.exit(1)
50 |
51 | trie: TrieRegEx = TrieRegEx()
52 |
53 | # loop through all args and attempt to parse
54 | for arg in args:
55 | # if arg is file and ends with .inc, then parse it
56 | if os.path.isfile(arg):
57 | if args.endswith('.inc'):
58 | with open(arg) as f: parse_file(f, trie)
59 | elif os.path.isdir(arg):
60 | parse_directory(PurePath(arg), parsedargs.recursive, trie)
61 |
62 | result: str = trie.regex()
63 | Debug.log('-- Result: --\n{}'.format(result))
64 |
65 | if result:
66 | pyperclip.copy(result)
67 | print('Output copied to clipboard (Len: {})'.format(len(result)))
68 | else:
69 | print('No results')
70 |
71 |
72 | def parse_directory(dir: PathLike, recursive: bool, trie: TrieRegEx) -> None:
73 | """
74 | Attempts to parse files within the given directory
75 |
76 | Args:
77 | dir (str): The directory to crawl through
78 | recursive (bool): If true, crawls through all subdirectories
79 | trie (TrieRegEx): The trie to add results to.
80 | """
81 | if recursive:
82 | for path, _, files in os.walk(dir):
83 | for name in files:
84 | if name.endswith('.inc'):
85 | with open(os.path.join(path, name)) as f: parse_file(f, trie)
86 | else:
87 | # loop through each file in the directory
88 | for file_name in os.listdir(dir):
89 | # if it's not a .inc file, skip it
90 | if not file_name.endswith('.inc'): continue
91 |
92 | # open and read the file
93 | with open(os.path.join(dir, file_name)) as f: parse_file(f, trie)
94 |
95 |
96 | def parse_file(f: TextIOWrapper, trie: TrieRegEx) -> None:
97 | """
98 | Parses a file for constants and adds them to the regex trie
99 |
100 | Args:
101 | f (TextIOWrapper): The file to parse
102 | tre (TrieRegEx): The trie to add results to.
103 | """
104 | Debug.log('-- Reading from {} --'.format(f.name))
105 |
106 | code: str = f.read()
107 |
108 | # remove multi-line comments
109 | code = re.sub(r'/\*(.|\n)*?\*/', '', code)
110 | #remove single-line comments
111 | code = re.sub(r'//.*$', '', code)
112 |
113 | parse_enums(code, trie)
114 | parse_defines(code, trie)
115 | parse_publicconstants(code, trie)
116 |
117 |
118 | def parse_enums(code: str, trie: TrieRegEx) -> None:
119 | """
120 | Finds enum values and adds them to the regex trie
121 |
122 | Args:
123 | code (str): Text to search through.
124 | trie (TrieRegEx): Trie to add results to.
125 | """
126 | # scoop the innards from all enums, excluding enum structs
127 | for enum_innards_match in re.finditer(r'enum(?!\s+struct)(?:.|\n)*?{((?:.|\n)*?)}', code):
128 | Debug.log('-- Enum match: --\n{}\n-------'.format(enum_innards_match.group(0)))
129 | enum_innards: str = enum_innards_match.group(1)
130 |
131 | # try to get each enum variable
132 | for enum_def_match in re.finditer(r'(?:^|\n)\s*?(\w+)\b', enum_innards):
133 | def_text: str = enum_def_match.group(1)
134 |
135 | # if it's all uppercase, skip it
136 | if (re.match(r'\b[A-Z_\d]+\b', def_text)): continue
137 |
138 | # skip if already contains
139 | if (trie.has(def_text)):
140 | Debug.log('Skipping enum, already added: {}'.format(def_text))
141 | continue
142 |
143 | trie.add(def_text)
144 | Debug.log('Enum added: {}'.format(def_text))
145 |
146 |
147 | def parse_defines(code: str, trie: TrieRegEx) -> None:
148 | """
149 | Finds defines and adds them to the regex trie
150 |
151 | Args:
152 | code (str): Text to search through.
153 | trie (TrieRegEx): Trie to add results to.
154 | """
155 | # match all defines
156 | for define_match in re.finditer(r'^#define[ \t]*(\w+)\b[ \t]', code):
157 | define: str = define_match.group(1)
158 |
159 | # if all uppercase, ignore. Typically they should be uppercase but maybe there's an exception
160 | if (re.match(r'\b[A-Z_\d]+\b', define)): continue
161 |
162 | # skip if already contains
163 | if (trie.has(define)):
164 | Debug.log('Skipping define, already added: {}'.format(define))
165 | continue
166 |
167 | trie.add(define)
168 | Debug.log('Define added: {}'.format(define))
169 |
170 |
171 | def parse_publicconstants(code: str, trie: TrieRegEx) -> None:
172 | """
173 | Finds public const variables and adds them to the regex trie
174 |
175 | Args:
176 | code (str): Text to search through.
177 | trie (TrieRegEx): Trie to add results to.
178 | """
179 | # match public constants aka magic variables
180 | for constant_match in re.finditer(r'public[ \t]+const[ \t]+\w+[ \t]+(\w+)\b', code):
181 | constant: str = constant_match.group(1)
182 |
183 | # if all uppercase, ignore
184 | if (re.match(r'\b[A-Z_\d]+\b', constant)): continue
185 |
186 | # skip if already contains
187 | if (trie.has(constant)):
188 | Debug.log('Skipping const, already added: {}'.format(constant))
189 | continue
190 |
191 | trie.add(constant)
192 | Debug.log('Const added: {}'.format(constant))
193 |
194 |
195 | # -------------
196 | if __name__ == '__main__': main(parsedargs.paths)
197 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/notes.txt:
--------------------------------------------------------------------------------
1 | "sublime_text": ">4070"
2 |
3 | 2:20 PM] OdatNurd:
4 | >>> panel = window.create_output_panel('my_panel', unlisted=True)
5 | >>> panel.assign_syntax("Packages/Python/Python.sublime-syntax")
6 | >>> panel.run_command("append", {"characters": "import sublime"})
7 | >>> panel.scope_name(0)
8 | 'source.python meta.statement.import.python keyword.control.import.python '
9 | [2:21 PM] OdatNurd: also this may be a handy addition:
10 | [2:21 PM] OdatNurd:
11 | >>> panel.extract_tokens_with_scopes(sublime.Region(0, len(panel)))
12 | [((0, 6), 'source.python meta.statement.import.python keyword.control.import.python '), ((6, 7), 'source.python meta.statement.import.python '), ((7, 14), 'source.python meta.statement.import.python meta.qualified-name.python meta.generic-name.python ')]
13 | [2:22 PM] JoinedSenses: alright, thank you. another question. ive managed to grab a bunch of regions that consist of lets say, variable declarations. is there api to maybe split it up or grab all words within that region that are something like variable.other.readwrite
14 | [2:22 PM] OdatNurd: i.e. grab individual tokens with scopes applied over a region, which here is the whole panel content but you could target that
15 | [2:23 PM] OdatNurd: view.substr() gives you the text of any particular region as a string
16 | [2:24 PM] JoinedSenses: yeah, i've got the entire region as a string. trying to find a way to pull certain words from it
17 | [2:24 PM] OdatNurd: if you have say a region that covers a whole function and you just want the variables defined inside that, then you would need to do something like call view.find_by_selector('variable.other.readwrite') to get all of the variables, and then determine which of those results is inside of the region that wraps the function
18 | [2:24 PM] OdatNurd: region.contains() will tell you if one region contains another one
19 | [2:24 PM] JoinedSenses: cool thanks. that was my backup plan
20 | [2:25 PM] JoinedSenses: trying to do two things, get the type of variables and also only add variables in global and current local scope for autocompletion
21 | [2:26 PM] OdatNurd: depending on what you're trying to do, you could also combine this with the above; fill the hidden output panel with the function delcaration and then you're good to go. That may or may not be handy based on where and when you need the info though; also it requires that the syntax could still highlight things properly with only partial content, etc
22 | [2:26 PM] JoinedSenses: alright. i saved those references and will see if i can make sense/use of it
23 | [2:26 PM] JoinedSenses: thank you
--------------------------------------------------------------------------------
/Packages/SourcePawn/pathtools/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pathtools: File system path tools.
3 | # Copyright (C) 2010 Yesudeep Mangalapilly
4 | #
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
6 | # of this software and associated documentation files (the "Software"), to deal
7 | # in the Software without restriction, including without limitation the rights
8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the Software is
10 | # furnished to do so, subject to the following conditions:
11 | #
12 | # The above copyright notice and this permission notice shall be included in
13 | # all copies or substantial portions of the Software.
14 | #
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | # THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/pathtools/path.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # path.py: Path functions.
4 | #
5 | # Copyright (C) 2010 Yesudeep Mangalapilly
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in
15 | # all copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | # THE SOFTWARE.
24 |
25 | """
26 | :module: pathtools.path
27 | :synopsis: Directory walking, listing, and path sanitizing functions.
28 | :author: Yesudeep Mangalapilly
29 |
30 | Functions
31 | ---------
32 | .. autofunction:: get_dir_walker
33 | .. autofunction:: walk
34 | .. autofunction:: listdir
35 | .. autofunction:: list_directories
36 | .. autofunction:: list_files
37 | .. autofunction:: absolute_path
38 | .. autofunction:: real_absolute_path
39 | .. autofunction:: parent_dir_path
40 | """
41 |
42 | import os.path
43 | from functools import partial
44 |
45 |
46 | __all__ = [
47 | 'get_dir_walker',
48 | 'walk',
49 | 'listdir',
50 | 'list_directories',
51 | 'list_files',
52 | 'absolute_path',
53 | 'real_absolute_path',
54 | 'parent_dir_path',
55 | ]
56 |
57 |
58 | def get_dir_walker(recursive, topdown=True, followlinks=False):
59 | """
60 | Returns a recursive or a non-recursive directory walker.
61 |
62 | :param recursive:
63 | ``True`` produces a recursive walker; ``False`` produces a non-recursive
64 | walker.
65 | :returns:
66 | A walker function.
67 | """
68 | if recursive:
69 | walk = partial(os.walk, topdown=topdown, followlinks=followlinks)
70 | else:
71 | def walk(path, topdown=topdown, followlinks=followlinks):
72 | try:
73 | yield next(os.walk(path, topdown=topdown, followlinks=followlinks))
74 | except NameError:
75 | yield os.walk(path, topdown=topdown, followlinks=followlinks).next() #IGNORE:E1101
76 | return walk
77 |
78 |
79 | def walk(dir_pathname, recursive=True, topdown=True, followlinks=False):
80 | """
81 | Walks a directory tree optionally recursively. Works exactly like
82 | :func:`os.walk` only adding the `recursive` argument.
83 |
84 | :param dir_pathname:
85 | The directory to traverse.
86 | :param recursive:
87 | ``True`` for walking recursively through the directory tree;
88 | ``False`` otherwise.
89 | :param topdown:
90 | Please see the documentation for :func:`os.walk`
91 | :param followlinks:
92 | Please see the documentation for :func:`os.walk`
93 | """
94 | walk_func = get_dir_walker(recursive, topdown, followlinks)
95 | for root, dirnames, filenames in walk_func(dir_pathname):
96 | yield (root, dirnames, filenames)
97 |
98 |
99 | def listdir(dir_pathname,
100 | recursive=True,
101 | topdown=True,
102 | followlinks=False):
103 | """
104 | Enlists all items using their absolute paths in a directory, optionally
105 | recursively.
106 |
107 | :param dir_pathname:
108 | The directory to traverse.
109 | :param recursive:
110 | ``True`` for walking recursively through the directory tree;
111 | ``False`` otherwise.
112 | :param topdown:
113 | Please see the documentation for :func:`os.walk`
114 | :param followlinks:
115 | Please see the documentation for :func:`os.walk`
116 | """
117 | for root, dirnames, filenames\
118 | in walk(dir_pathname, recursive, topdown, followlinks):
119 | for dirname in dirnames:
120 | yield absolute_path(os.path.join(root, dirname))
121 | for filename in filenames:
122 | yield absolute_path(os.path.join(root, filename))
123 |
124 |
125 | def list_directories(dir_pathname,
126 | recursive=True,
127 | topdown=True,
128 | followlinks=False):
129 | """
130 | Enlists all the directories using their absolute paths within the specified
131 | directory, optionally recursively.
132 |
133 | :param dir_pathname:
134 | The directory to traverse.
135 | :param recursive:
136 | ``True`` for walking recursively through the directory tree;
137 | ``False`` otherwise.
138 | :param topdown:
139 | Please see the documentation for :func:`os.walk`
140 | :param followlinks:
141 | Please see the documentation for :func:`os.walk`
142 | """
143 | for root, dirnames, filenames\
144 | in walk(dir_pathname, recursive, topdown, followlinks):
145 | for dirname in dirnames:
146 | yield absolute_path(os.path.join(root, dirname))
147 |
148 |
149 | def list_files(dir_pathname,
150 | recursive=True,
151 | topdown=True,
152 | followlinks=False):
153 | """
154 | Enlists all the files using their absolute paths within the specified
155 | directory, optionally recursively.
156 |
157 | :param dir_pathname:
158 | The directory to traverse.
159 | :param recursive:
160 | ``True`` for walking recursively through the directory tree;
161 | ``False`` otherwise.
162 | :param topdown:
163 | Please see the documentation for :func:`os.walk`
164 | :param followlinks:
165 | Please see the documentation for :func:`os.walk`
166 | """
167 | for root, dirnames, filenames\
168 | in walk(dir_pathname, recursive, topdown, followlinks):
169 | for filename in filenames:
170 | yield absolute_path(os.path.join(root, filename))
171 |
172 |
173 | def absolute_path(path):
174 | """
175 | Returns the absolute path for the given path and normalizes the path.
176 |
177 | :param path:
178 | Path for which the absolute normalized path will be found.
179 | :returns:
180 | Absolute normalized path.
181 | """
182 | return os.path.abspath(os.path.normpath(path))
183 |
184 |
185 | def real_absolute_path(path):
186 | """
187 | Returns the real absolute normalized path for the given path.
188 |
189 | :param path:
190 | Path for which the real absolute normalized path will be found.
191 | :returns:
192 | Real absolute normalized path.
193 | """
194 | return os.path.realpath(absolute_path(path))
195 |
196 |
197 | def parent_dir_path(path):
198 | """
199 | Returns the parent directory path.
200 |
201 | :param path:
202 | Path for which the parent directory will be obtained.
203 | :returns:
204 | Parent directory path.
205 | """
206 | return absolute_path(os.path.dirname(path))
207 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/pathtools/patterns.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # patterns.py: Common wildcard searching/filtering functionality for files.
4 | #
5 | # Copyright (C) 2010 Yesudeep Mangalapilly
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in
15 | # all copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | # THE SOFTWARE.
24 |
25 | """
26 | :module: pathtools.patterns
27 | :synopsis: Wildcard pattern matching and filtering functions for paths.
28 | :author: Yesudeep Mangalapilly
29 |
30 | Functions
31 | ---------
32 | .. autofunction:: match_path
33 | .. autofunction:: match_path_against
34 | .. autofunction:: filter_paths
35 | """
36 |
37 | from fnmatch import fnmatch, fnmatchcase
38 |
39 | __all__ = ['match_path',
40 | 'match_path_against',
41 | 'match_any_paths',
42 | 'filter_paths']
43 |
44 |
45 | def _string_lower(s):
46 | """
47 | Convenience function to lowercase a string (the :mod:`string` module is
48 | deprecated/removed in Python 3.0).
49 |
50 | :param s:
51 | The string which will be lowercased.
52 | :returns:
53 | Lowercased copy of string s.
54 | """
55 | return s.lower()
56 |
57 |
58 | def match_path_against(pathname, patterns, case_sensitive=True):
59 | """
60 | Determines whether the pathname matches any of the given wildcard patterns,
61 | optionally ignoring the case of the pathname and patterns.
62 |
63 | :param pathname:
64 | A path name that will be matched against a wildcard pattern.
65 | :param patterns:
66 | A list of wildcard patterns to match_path the filename against.
67 | :param case_sensitive:
68 | ``True`` if the matching should be case-sensitive; ``False`` otherwise.
69 | :returns:
70 | ``True`` if the pattern matches; ``False`` otherwise.
71 |
72 | Doctests::
73 | >>> match_path_against("/home/username/foobar/blah.py", ["*.py", "*.txt"], False)
74 | True
75 | >>> match_path_against("/home/username/foobar/blah.py", ["*.PY", "*.txt"], True)
76 | False
77 | >>> match_path_against("/home/username/foobar/blah.py", ["*.PY", "*.txt"], False)
78 | True
79 | >>> match_path_against("C:\\windows\\blah\\BLAH.PY", ["*.py", "*.txt"], True)
80 | False
81 | >>> match_path_against("C:\\windows\\blah\\BLAH.PY", ["*.py", "*.txt"], False)
82 | True
83 | """
84 | if case_sensitive:
85 | match_func = fnmatchcase
86 | pattern_transform_func = (lambda w: w)
87 | else:
88 | match_func = fnmatch
89 | pathname = pathname.lower()
90 | pattern_transform_func = _string_lower
91 | for pattern in set(patterns):
92 | pattern = pattern_transform_func(pattern)
93 | if match_func(pathname, pattern):
94 | return True
95 | return False
96 |
97 |
98 | def _match_path(pathname,
99 | included_patterns,
100 | excluded_patterns,
101 | case_sensitive=True):
102 | """Internal function same as :func:`match_path` but does not check arguments.
103 |
104 | Doctests::
105 | >>> _match_path("/users/gorakhargosh/foobar.py", ["*.py"], ["*.PY"], True)
106 | True
107 | >>> _match_path("/users/gorakhargosh/FOOBAR.PY", ["*.py"], ["*.PY"], True)
108 | False
109 | >>> _match_path("/users/gorakhargosh/foobar/", ["*.py"], ["*.txt"], False)
110 | False
111 | >>> _match_path("/users/gorakhargosh/FOOBAR.PY", ["*.py"], ["*.PY"], False)
112 | Traceback (most recent call last):
113 | ...
114 | ValueError: conflicting patterns `set(['*.py'])` included and excluded
115 | """
116 | if not case_sensitive:
117 | included_patterns = set(map(_string_lower, included_patterns))
118 | excluded_patterns = set(map(_string_lower, excluded_patterns))
119 | else:
120 | included_patterns = set(included_patterns)
121 | excluded_patterns = set(excluded_patterns)
122 | common_patterns = included_patterns & excluded_patterns
123 | if common_patterns:
124 | raise ValueError('conflicting patterns `%s` included and excluded'\
125 | % common_patterns)
126 | return (match_path_against(pathname, included_patterns, case_sensitive)\
127 | and not match_path_against(pathname, excluded_patterns,
128 | case_sensitive))
129 |
130 |
131 | def match_path(pathname,
132 | included_patterns=None,
133 | excluded_patterns=None,
134 | case_sensitive=True):
135 | """
136 | Matches a pathname against a set of acceptable and ignored patterns.
137 |
138 | :param pathname:
139 | A pathname which will be matched against a pattern.
140 | :param included_patterns:
141 | Allow filenames matching wildcard patterns specified in this list.
142 | If no pattern is specified, the function treats the pathname as
143 | a match_path.
144 | :param excluded_patterns:
145 | Ignores filenames matching wildcard patterns specified in this list.
146 | If no pattern is specified, the function treats the pathname as
147 | a match_path.
148 | :param case_sensitive:
149 | ``True`` if matching should be case-sensitive; ``False`` otherwise.
150 | :returns:
151 | ``True`` if the pathname matches; ``False`` otherwise.
152 | :raises:
153 | ValueError if included patterns and excluded patterns contain the
154 | same pattern.
155 |
156 | Doctests::
157 | >>> match_path("/Users/gorakhargosh/foobar.py")
158 | True
159 | >>> match_path("/Users/gorakhargosh/foobar.py", case_sensitive=False)
160 | True
161 | >>> match_path("/users/gorakhargosh/foobar.py", ["*.py"], ["*.PY"], True)
162 | True
163 | >>> match_path("/users/gorakhargosh/FOOBAR.PY", ["*.py"], ["*.PY"], True)
164 | False
165 | >>> match_path("/users/gorakhargosh/foobar/", ["*.py"], ["*.txt"], False)
166 | False
167 | >>> match_path("/users/gorakhargosh/FOOBAR.PY", ["*.py"], ["*.PY"], False)
168 | Traceback (most recent call last):
169 | ...
170 | ValueError: conflicting patterns `set(['*.py'])` included and excluded
171 | """
172 | included = ["*"] if included_patterns is None else included_patterns
173 | excluded = [] if excluded_patterns is None else excluded_patterns
174 | return _match_path(pathname, included, excluded, case_sensitive)
175 |
176 |
177 | def filter_paths(pathnames,
178 | included_patterns=None,
179 | excluded_patterns=None,
180 | case_sensitive=True):
181 | """
182 | Filters from a set of paths based on acceptable patterns and
183 | ignorable patterns.
184 |
185 | :param pathnames:
186 | A list of path names that will be filtered based on matching and
187 | ignored patterns.
188 | :param included_patterns:
189 | Allow filenames matching wildcard patterns specified in this list.
190 | If no pattern list is specified, ["*"] is used as the default pattern,
191 | which matches all files.
192 | :param excluded_patterns:
193 | Ignores filenames matching wildcard patterns specified in this list.
194 | If no pattern list is specified, no files are ignored.
195 | :param case_sensitive:
196 | ``True`` if matching should be case-sensitive; ``False`` otherwise.
197 | :returns:
198 | A list of pathnames that matched the allowable patterns and passed
199 | through the ignored patterns.
200 |
201 | Doctests::
202 | >>> pathnames = set(["/users/gorakhargosh/foobar.py", "/var/cache/pdnsd.status", "/etc/pdnsd.conf", "/usr/local/bin/python"])
203 | >>> set(filter_paths(pathnames)) == pathnames
204 | True
205 | >>> set(filter_paths(pathnames, case_sensitive=False)) == pathnames
206 | True
207 | >>> set(filter_paths(pathnames, ["*.py", "*.conf"], ["*.status"], case_sensitive=True)) == set(["/users/gorakhargosh/foobar.py", "/etc/pdnsd.conf"])
208 | True
209 | """
210 | included = ["*"] if included_patterns is None else included_patterns
211 | excluded = [] if excluded_patterns is None else excluded_patterns
212 |
213 | for pathname in pathnames:
214 | # We don't call the public match_path because it checks arguments
215 | # and sets default values if none are found. We're already doing that
216 | # above.
217 | if _match_path(pathname, included, excluded, case_sensitive):
218 | yield pathname
219 |
220 | def match_any_paths(pathnames,
221 | included_patterns=None,
222 | excluded_patterns=None,
223 | case_sensitive=True):
224 | """
225 | Matches from a set of paths based on acceptable patterns and
226 | ignorable patterns.
227 |
228 | :param pathnames:
229 | A list of path names that will be filtered based on matching and
230 | ignored patterns.
231 | :param included_patterns:
232 | Allow filenames matching wildcard patterns specified in this list.
233 | If no pattern list is specified, ["*"] is used as the default pattern,
234 | which matches all files.
235 | :param excluded_patterns:
236 | Ignores filenames matching wildcard patterns specified in this list.
237 | If no pattern list is specified, no files are ignored.
238 | :param case_sensitive:
239 | ``True`` if matching should be case-sensitive; ``False`` otherwise.
240 | :returns:
241 | ``True`` if any of the paths matches; ``False`` otherwise.
242 |
243 | Doctests::
244 | >>> pathnames = set(["/users/gorakhargosh/foobar.py", "/var/cache/pdnsd.status", "/etc/pdnsd.conf", "/usr/local/bin/python"])
245 | >>> match_any_paths(pathnames)
246 | True
247 | >>> match_any_paths(pathnames, case_sensitive=False)
248 | True
249 | >>> match_any_paths(pathnames, ["*.py", "*.conf"], ["*.status"], case_sensitive=True)
250 | True
251 | >>> match_any_paths(pathnames, ["*.txt"], case_sensitive=False)
252 | False
253 | >>> match_any_paths(pathnames, ["*.txt"], case_sensitive=True)
254 | False
255 | """
256 | included = ["*"] if included_patterns is None else included_patterns
257 | excluded = [] if excluded_patterns is None else excluded_patterns
258 |
259 | for pathname in pathnames:
260 | # We don't call the public match_path because it checks arguments
261 | # and sets default values if none are found. We're already doing that
262 | # above.
263 | if _match_path(pathname, included, excluded, case_sensitive):
264 | return True
265 | return False
266 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/pathtools/version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # version.py: Version information.
3 | # Copyright (C) 2010 Yesudeep Mangalapilly
4 | #
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
6 | # of this software and associated documentation files (the "Software"), to deal
7 | # in the Software without restriction, including without limitation the rights
8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the Software is
10 | # furnished to do so, subject to the following conditions:
11 | #
12 | # The above copyright notice and this permission notice shall be included in
13 | # all copies or substantial portions of the Software.
14 | #
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | # THE SOFTWARE.
22 |
23 | # When updating this version number, please update the
24 | # ``docs/source/global.rst.inc`` file as well.
25 | VERSION_MAJOR = 0
26 | VERSION_MINOR = 1
27 | VERSION_BUILD = 1
28 | VERSION_INFO = (VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD)
29 | VERSION_STRING = "%d.%d.%d" % VERSION_INFO
30 |
31 | __version__ = VERSION_INFO
32 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/observers/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 | """
20 | :module: watchdog.observers
21 | :synopsis: Observer that picks a native implementation if available.
22 | :author: yesudeep@google.com (Yesudeep Mangalapilly)
23 |
24 |
25 | Classes
26 | =======
27 | .. autoclass:: Observer
28 | :members:
29 | :show-inheritance:
30 | :inherited-members:
31 |
32 | Observer thread that schedules watching directories and dispatches
33 | calls to event handlers.
34 |
35 | You can also import platform specific classes directly and use it instead
36 | of :class:`Observer`. Here is a list of implemented observer classes.:
37 |
38 | ============== ================================ ==============================
39 | Class Platforms Note
40 | ============== ================================ ==============================
41 | |Inotify| Linux 2.6.13+ ``inotify(7)`` based observer
42 | |FSEvents| Mac OS X FSEvents based observer
43 | |Kqueue| Mac OS X and BSD with kqueue(2) ``kqueue(2)`` based observer
44 | |WinApi| MS Windows Windows API-based observer
45 | |Polling| Any fallback implementation
46 | ============== ================================ ==============================
47 |
48 | .. |Inotify| replace:: :class:`.inotify.InotifyObserver`
49 | .. |FSEvents| replace:: :class:`.fsevents.FSEventsObserver`
50 | .. |Kqueue| replace:: :class:`.kqueue.KqueueObserver`
51 | .. |WinApi| replace:: :class:`.read_directory_changes.WindowsApiObserver`
52 | .. |WinApiAsync| replace:: :class:`.read_directory_changes_async.WindowsApiAsyncObserver`
53 | .. |Polling| replace:: :class:`.polling.PollingObserver`
54 |
55 | """
56 |
57 | import warnings
58 | from watchdog.utils import platform
59 |
60 | if platform.is_linux():
61 | from .inotify import InotifyObserver as Observer
62 |
63 | elif platform.is_darwin():
64 | try:
65 | from .fsevents import FSEventsObserver as Observer
66 | except:
67 | from .kqueue import KqueueObserver as Observer
68 | warnings.warn("Failed to import fsevents. Fall back to kqueue")
69 |
70 | elif platform.is_bsd():
71 | from .kqueue import KqueueObserver as Observer
72 |
73 | elif platform.is_windows():
74 | # TODO: find a reliable way of checking Windows version and import
75 | # polling explicitly for Windows XP
76 | try:
77 | from .read_directory_changes import WindowsApiObserver as Observer
78 | except:
79 | from .polling import PollingObserver as Observer
80 | warnings.warn("Failed to import read_directory_changes. Fall back to polling.")
81 |
82 | else:
83 | from .polling import PollingObserver as Observer
84 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/observers/fsevents.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 | """
20 | :module: watchdog.observers.fsevents
21 | :synopsis: FSEvents based emitter implementation.
22 | :author: yesudeep@google.com (Yesudeep Mangalapilly)
23 | :platforms: Mac OS X
24 | """
25 |
26 | from __future__ import with_statement
27 |
28 | import sys
29 | import threading
30 | import unicodedata
31 | import _watchdog_fsevents as _fsevents
32 |
33 | from watchdog.events import (
34 | FileDeletedEvent,
35 | FileModifiedEvent,
36 | FileCreatedEvent,
37 | FileMovedEvent,
38 | DirDeletedEvent,
39 | DirModifiedEvent,
40 | DirCreatedEvent,
41 | DirMovedEvent
42 | )
43 |
44 | from watchdog.utils.dirsnapshot import DirectorySnapshot
45 | from watchdog.observers.api import (
46 | BaseObserver,
47 | EventEmitter,
48 | DEFAULT_EMITTER_TIMEOUT,
49 | DEFAULT_OBSERVER_TIMEOUT
50 | )
51 |
52 |
53 | class FSEventsEmitter(EventEmitter):
54 |
55 | """
56 | Mac OS X FSEvents Emitter class.
57 |
58 | :param event_queue:
59 | The event queue to fill with events.
60 | :param watch:
61 | A watch object representing the directory to monitor.
62 | :type watch:
63 | :class:`watchdog.observers.api.ObservedWatch`
64 | :param timeout:
65 | Read events blocking timeout (in seconds).
66 | :type timeout:
67 | ``float``
68 | """
69 |
70 | def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT):
71 | EventEmitter.__init__(self, event_queue, watch, timeout)
72 | self._lock = threading.Lock()
73 | self.snapshot = DirectorySnapshot(watch.path, watch.is_recursive)
74 |
75 | def on_thread_stop(self):
76 | _fsevents.remove_watch(self.watch)
77 | _fsevents.stop(self)
78 |
79 | def queue_events(self, timeout):
80 | with self._lock:
81 | if not self.watch.is_recursive\
82 | and self.watch.path not in self.pathnames:
83 | return
84 | new_snapshot = DirectorySnapshot(self.watch.path,
85 | self.watch.is_recursive)
86 | events = new_snapshot - self.snapshot
87 | self.snapshot = new_snapshot
88 |
89 | # Files.
90 | for src_path in events.files_deleted:
91 | self.queue_event(FileDeletedEvent(src_path))
92 | for src_path in events.files_modified:
93 | self.queue_event(FileModifiedEvent(src_path))
94 | for src_path in events.files_created:
95 | self.queue_event(FileCreatedEvent(src_path))
96 | for src_path, dest_path in events.files_moved:
97 | self.queue_event(FileMovedEvent(src_path, dest_path))
98 |
99 | # Directories.
100 | for src_path in events.dirs_deleted:
101 | self.queue_event(DirDeletedEvent(src_path))
102 | for src_path in events.dirs_modified:
103 | self.queue_event(DirModifiedEvent(src_path))
104 | for src_path in events.dirs_created:
105 | self.queue_event(DirCreatedEvent(src_path))
106 | for src_path, dest_path in events.dirs_moved:
107 | self.queue_event(DirMovedEvent(src_path, dest_path))
108 |
109 | def run(self):
110 | try:
111 | def callback(pathnames, flags, emitter=self):
112 | emitter.queue_events(emitter.timeout)
113 |
114 | # for pathname, flag in zip(pathnames, flags):
115 | # if emitter.watch.is_recursive: # and pathname != emitter.watch.path:
116 | # new_sub_snapshot = DirectorySnapshot(pathname, True)
117 | # old_sub_snapshot = self.snapshot.copy(pathname)
118 | # diff = new_sub_snapshot - old_sub_snapshot
119 | # self.snapshot += new_subsnapshot
120 | # else:
121 | # new_snapshot = DirectorySnapshot(emitter.watch.path, False)
122 | # diff = new_snapshot - emitter.snapshot
123 | # emitter.snapshot = new_snapshot
124 |
125 | # INFO: FSEvents reports directory notifications recursively
126 | # by default, so we do not need to add subdirectory paths.
127 | #pathnames = set([self.watch.path])
128 | # if self.watch.is_recursive:
129 | # for root, directory_names, _ in os.walk(self.watch.path):
130 | # for directory_name in directory_names:
131 | # full_path = absolute_path(
132 | # os.path.join(root, directory_name))
133 | # pathnames.add(full_path)
134 | self.pathnames = [self.watch.path]
135 | _fsevents.add_watch(self,
136 | self.watch,
137 | callback,
138 | self.pathnames)
139 | _fsevents.read_events(self)
140 | except Exception as e:
141 | pass
142 |
143 |
144 | class FSEventsObserver(BaseObserver):
145 |
146 | def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT):
147 | BaseObserver.__init__(self, emitter_class=FSEventsEmitter,
148 | timeout=timeout)
149 |
150 | def schedule(self, event_handler, path, recursive=False):
151 | # Python 2/3 compat
152 | try:
153 | str_class = unicode
154 | except NameError:
155 | str_class = str
156 |
157 | # Fix for issue #26: Trace/BPT error when given a unicode path
158 | # string. https://github.com/gorakhargosh/watchdog/issues#issue/26
159 | if isinstance(path, str_class):
160 | #path = unicode(path, 'utf-8')
161 | path = unicodedata.normalize('NFC', path)
162 | # We only encode the path in Python 2 for backwards compatibility.
163 | # On Python 3 we want the path to stay as unicode if possible for
164 | # the sake of path matching not having to be rewritten to use the
165 | # bytes API instead of strings. The _watchdog_fsevent.so code for
166 | # Python 3 can handle both str and bytes paths, which is why we
167 | # do not HAVE to encode it with Python 3. The Python 2 code in
168 | # _watchdog_fsevents.so was not changed for the sake of backwards
169 | # compatibility.
170 | if sys.version_info < (3,):
171 | path = path.encode('utf-8')
172 | return BaseObserver.schedule(self, event_handler, path, recursive)
173 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/observers/fsevents2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright 2014 Thomas Amland
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """
18 | :module: watchdog.observers.fsevents2
19 | :synopsis: FSEvents based emitter implementation.
20 | :platforms: Mac OS X
21 | """
22 |
23 | import os
24 | import logging
25 | import unicodedata
26 | from threading import Thread
27 | from watchdog.utils.compat import queue
28 |
29 | from watchdog.events import (
30 | FileDeletedEvent,
31 | FileModifiedEvent,
32 | FileCreatedEvent,
33 | FileMovedEvent,
34 | DirDeletedEvent,
35 | DirModifiedEvent,
36 | DirCreatedEvent,
37 | DirMovedEvent
38 | )
39 | from watchdog.observers.api import (
40 | BaseObserver,
41 | EventEmitter,
42 | DEFAULT_EMITTER_TIMEOUT,
43 | DEFAULT_OBSERVER_TIMEOUT,
44 | )
45 |
46 | # pyobjc
47 | import AppKit
48 | from FSEvents import (
49 | FSEventStreamCreate,
50 | CFRunLoopGetCurrent,
51 | FSEventStreamScheduleWithRunLoop,
52 | FSEventStreamStart,
53 | CFRunLoopRun,
54 | CFRunLoopStop,
55 | FSEventStreamStop,
56 | FSEventStreamInvalidate,
57 | FSEventStreamRelease,
58 | )
59 |
60 | from FSEvents import (
61 | kCFAllocatorDefault,
62 | kCFRunLoopDefaultMode,
63 | kFSEventStreamEventIdSinceNow,
64 | kFSEventStreamCreateFlagNoDefer,
65 | kFSEventStreamCreateFlagFileEvents,
66 | kFSEventStreamEventFlagItemCreated,
67 | kFSEventStreamEventFlagItemRemoved,
68 | kFSEventStreamEventFlagItemInodeMetaMod,
69 | kFSEventStreamEventFlagItemRenamed,
70 | kFSEventStreamEventFlagItemModified,
71 | kFSEventStreamEventFlagItemFinderInfoMod,
72 | kFSEventStreamEventFlagItemChangeOwner,
73 | kFSEventStreamEventFlagItemXattrMod,
74 | kFSEventStreamEventFlagItemIsFile,
75 | kFSEventStreamEventFlagItemIsDir,
76 | kFSEventStreamEventFlagItemIsSymlink,
77 | )
78 |
79 |
80 | class FSEventsQueue(Thread):
81 | """ Low level FSEvents client. """
82 |
83 | def __init__(self, path):
84 | Thread.__init__(self)
85 | self._queue = queue.Queue()
86 | self._run_loop = None
87 |
88 | if isinstance(path, bytes):
89 | self._path = path.decode('utf-8')
90 | self._path = unicodedata.normalize('NFC', self._path)
91 |
92 | context = None
93 | latency = 1.0
94 | self._stream_ref = FSEventStreamCreate(
95 | kCFAllocatorDefault, self._callback, context, [self._path],
96 | kFSEventStreamEventIdSinceNow, latency,
97 | kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents)
98 | if self._stream_ref is None:
99 | raise IOError("FSEvents. Could not create stream.")
100 |
101 | def run(self):
102 | pool = AppKit.NSAutoreleasePool.alloc().init()
103 | self._run_loop = CFRunLoopGetCurrent()
104 | FSEventStreamScheduleWithRunLoop(
105 | self._stream_ref, self._run_loop, kCFRunLoopDefaultMode)
106 | if not FSEventStreamStart(self._stream_ref):
107 | FSEventStreamInvalidate(self._stream_ref)
108 | FSEventStreamRelease(self._stream_ref)
109 | raise IOError("FSEvents. Could not start stream.")
110 |
111 | CFRunLoopRun()
112 | FSEventStreamStop(self._stream_ref)
113 | FSEventStreamInvalidate(self._stream_ref)
114 | FSEventStreamRelease(self._stream_ref)
115 | del pool
116 | # Make sure waiting thread is notified
117 | self._queue.put(None)
118 |
119 | def stop(self):
120 | if self._run_loop is not None:
121 | CFRunLoopStop(self._run_loop)
122 |
123 | def _callback(self, streamRef, clientCallBackInfo, numEvents, eventPaths, eventFlags, eventIDs):
124 | events = [NativeEvent(path, flags, _id) for path, flags, _id in
125 | zip(eventPaths, eventFlags, eventIDs)]
126 | logging.debug("FSEvents callback. Got %d events:" % numEvents)
127 | for e in events:
128 | logging.debug(e)
129 | self._queue.put(events)
130 |
131 | def read_events(self):
132 | """
133 | Returns a list or one or more events, or None if there are no more
134 | events to be read.
135 | """
136 | if not self.is_alive():
137 | return None
138 | return self._queue.get()
139 |
140 |
141 | class NativeEvent(object):
142 | def __init__(self, path, flags, event_id):
143 | self.path = path
144 | self.flags = flags
145 | self.event_id = event_id
146 | self.is_created = bool(flags & kFSEventStreamEventFlagItemCreated)
147 | self.is_removed = bool(flags & kFSEventStreamEventFlagItemRemoved)
148 | self.is_renamed = bool(flags & kFSEventStreamEventFlagItemRenamed)
149 | self.is_modified = bool(flags & kFSEventStreamEventFlagItemModified)
150 | self.is_change_owner = bool(flags & kFSEventStreamEventFlagItemChangeOwner)
151 | self.is_inode_meta_mod = bool(flags & kFSEventStreamEventFlagItemInodeMetaMod)
152 | self.is_finder_info_mod = bool(flags & kFSEventStreamEventFlagItemFinderInfoMod)
153 | self.is_xattr_mod = bool(flags & kFSEventStreamEventFlagItemXattrMod)
154 | self.is_symlink = bool(flags & kFSEventStreamEventFlagItemIsSymlink)
155 | self.is_directory = bool(flags & kFSEventStreamEventFlagItemIsDir)
156 |
157 | @property
158 | def _event_type(self):
159 | if self.is_created: return "Created"
160 | if self.is_removed: return "Removed"
161 | if self.is_renamed: return "Renamed"
162 | if self.is_modified: return "Modified"
163 | if self.is_inode_meta_mod: return "InodeMetaMod"
164 | if self.is_xattr_mod: return "XattrMod"
165 | return "Unknown"
166 |
167 | def __repr__(self):
168 | s =""
169 | return s % (repr(self.path), self._event_type, self.is_directory, hex(self.flags), self.event_id)
170 |
171 |
172 | class FSEventsEmitter(EventEmitter):
173 | """
174 | FSEvents based event emitter. Handles conversion of native events.
175 | """
176 |
177 | def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT):
178 | EventEmitter.__init__(self, event_queue, watch, timeout)
179 | self._fsevents = FSEventsQueue(watch.path)
180 | self._fsevents.start()
181 |
182 | def on_thread_stop(self):
183 | self._fsevents.stop()
184 |
185 | def queue_events(self, timeout):
186 | events = self._fsevents.read_events()
187 | if events is None:
188 | return
189 | i = 0
190 | while i < len(events):
191 | event = events[i]
192 |
193 | # For some reason the create and remove flags are sometimes also
194 | # set for rename and modify type events, so let those take
195 | # precedence.
196 | if event.is_renamed:
197 | # Internal moves appears to always be consecutive in the same
198 | # buffer and have IDs differ by exactly one (while others
199 | # don't) making it possible to pair up the two events coming
200 | # from a singe move operation. (None of this is documented!)
201 | # Otherwise, guess whether file was moved in or out.
202 | #TODO: handle id wrapping
203 | if (i+1 < len(events) and events[i+1].is_renamed and
204 | events[i+1].event_id == event.event_id + 1):
205 | cls = DirMovedEvent if event.is_directory else FileMovedEvent
206 | self.queue_event(cls(event.path, events[i+1].path))
207 | self.queue_event(DirModifiedEvent(os.path.dirname(event.path)))
208 | self.queue_event(DirModifiedEvent(os.path.dirname(events[i+1].path)))
209 | i += 1
210 | elif os.path.exists(event.path):
211 | cls = DirCreatedEvent if event.is_directory else FileCreatedEvent
212 | self.queue_event(cls(event.path))
213 | self.queue_event(DirModifiedEvent(os.path.dirname(event.path)))
214 | else:
215 | cls = DirDeletedEvent if event.is_directory else FileDeletedEvent
216 | self.queue_event(cls(event.path))
217 | self.queue_event(DirModifiedEvent(os.path.dirname(event.path)))
218 | #TODO: generate events for tree
219 |
220 | elif event.is_modified or event.is_inode_meta_mod or event.is_xattr_mod :
221 | cls = DirModifiedEvent if event.is_directory else FileModifiedEvent
222 | self.queue_event(cls(event.path))
223 |
224 | elif event.is_created:
225 | cls = DirCreatedEvent if event.is_directory else FileCreatedEvent
226 | self.queue_event(cls(event.path))
227 | self.queue_event(DirModifiedEvent(os.path.dirname(event.path)))
228 |
229 | elif event.is_removed:
230 | cls = DirDeletedEvent if event.is_directory else FileDeletedEvent
231 | self.queue_event(cls(event.path))
232 | self.queue_event(DirModifiedEvent(os.path.dirname(event.path)))
233 | i += 1
234 |
235 |
236 | class FSEventsObserver2(BaseObserver):
237 | def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT):
238 | BaseObserver.__init__(self, emitter_class=FSEventsEmitter, timeout=timeout)
239 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/observers/inotify.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 | """
20 | :module: watchdog.observers.inotify
21 | :synopsis: ``inotify(7)`` based emitter implementation.
22 | :author: Sebastien Martini
23 | :author: Luke McCarthy
24 | :author: yesudeep@google.com (Yesudeep Mangalapilly)
25 | :author: Tim Cuthbertson
26 | :platforms: Linux 2.6.13+.
27 |
28 | .. ADMONITION:: About system requirements
29 |
30 | Recommended minimum kernel version: 2.6.25.
31 |
32 | Quote from the inotify(7) man page:
33 |
34 | "Inotify was merged into the 2.6.13 Linux kernel. The required library
35 | interfaces were added to glibc in version 2.4. (IN_DONT_FOLLOW,
36 | IN_MASK_ADD, and IN_ONLYDIR were only added in version 2.5.)"
37 |
38 | Therefore, you must ensure the system is running at least these versions
39 | appropriate libraries and the kernel.
40 |
41 | .. ADMONITION:: About recursiveness, event order, and event coalescing
42 |
43 | Quote from the inotify(7) man page:
44 |
45 | If successive output inotify events produced on the inotify file
46 | descriptor are identical (same wd, mask, cookie, and name) then they
47 | are coalesced into a single event if the older event has not yet been
48 | read (but see BUGS).
49 |
50 | The events returned by reading from an inotify file descriptor form
51 | an ordered queue. Thus, for example, it is guaranteed that when
52 | renaming from one directory to another, events will be produced in
53 | the correct order on the inotify file descriptor.
54 |
55 | ...
56 |
57 | Inotify monitoring of directories is not recursive: to monitor
58 | subdirectories under a directory, additional watches must be created.
59 |
60 | This emitter implementation therefore automatically adds watches for
61 | sub-directories if running in recursive mode.
62 |
63 | Some extremely useful articles and documentation:
64 |
65 | .. _inotify FAQ: http://inotify.aiken.cz/?section=inotify&page=faq&lang=en
66 | .. _intro to inotify: http://www.linuxjournal.com/article/8478
67 |
68 | """
69 |
70 | from __future__ import with_statement
71 |
72 | import os
73 | import threading
74 | from .inotify_buffer import InotifyBuffer, STOP_EVENT
75 |
76 | from watchdog.observers.api import (
77 | EventEmitter,
78 | BaseObserver,
79 | DEFAULT_EMITTER_TIMEOUT,
80 | DEFAULT_OBSERVER_TIMEOUT
81 | )
82 |
83 | from watchdog.events import (
84 | DirDeletedEvent,
85 | DirModifiedEvent,
86 | DirMovedEvent,
87 | DirCreatedEvent,
88 | FileDeletedEvent,
89 | FileModifiedEvent,
90 | FileMovedEvent,
91 | FileCreatedEvent,
92 | generate_sub_moved_events,
93 | generate_sub_created_events,
94 | )
95 | from watchdog.utils import unicode_paths
96 |
97 |
98 | class InotifyEmitter(EventEmitter):
99 | """
100 | inotify(7)-based event emitter.
101 |
102 | :param event_queue:
103 | The event queue to fill with events.
104 | :param watch:
105 | A watch object representing the directory to monitor.
106 | :type watch:
107 | :class:`watchdog.observers.api.ObservedWatch`
108 | :param timeout:
109 | Read events blocking timeout (in seconds).
110 | :type timeout:
111 | ``float``
112 | """
113 |
114 | def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT):
115 | EventEmitter.__init__(self, event_queue, watch, timeout)
116 | self._lock = threading.Lock()
117 | self._inotify = InotifyBuffer(unicode_paths.encode(watch.path),
118 | watch.is_recursive)
119 |
120 | def _decode_path(self, path):
121 | """ Decode path only if unicode string was passed to this emitter. """
122 | if isinstance(self.watch.path, bytes):
123 | return path
124 | return unicode_paths.decode(path)
125 |
126 | def on_thread_stop(self):
127 | self._inotify.close()
128 |
129 | def queue_events(self, timeout):
130 | with self._lock:
131 | event = self._inotify.read_event()
132 |
133 | if event is STOP_EVENT:
134 | return
135 |
136 | if isinstance(event, tuple):
137 | move_from, move_to = event
138 | src_path = self._decode_path(move_from.src_path)
139 | dest_path = self._decode_path(move_to.src_path)
140 | cls = DirMovedEvent if move_from.is_directory else FileMovedEvent
141 | self.queue_event(cls(src_path, dest_path))
142 | self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
143 | self.queue_event(DirModifiedEvent(os.path.dirname(dest_path)))
144 | if move_from.is_directory and self.watch.is_recursive:
145 | for sub_event in generate_sub_moved_events(src_path, dest_path):
146 | self.queue_event(sub_event)
147 | return
148 |
149 | src_path = self._decode_path(event.src_path)
150 | if event.is_moved_to:
151 | cls = DirCreatedEvent if event.is_directory else FileCreatedEvent
152 | self.queue_event(cls(src_path))
153 | self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
154 | if event.is_directory and self.watch.is_recursive:
155 | for sub_event in generate_sub_created_events(src_path):
156 | self.queue_event(sub_event)
157 | elif event.is_attrib:
158 | cls = DirModifiedEvent if event.is_directory else FileModifiedEvent
159 | self.queue_event(cls(src_path))
160 | elif event.is_modify:
161 | cls = DirModifiedEvent if event.is_directory else FileModifiedEvent
162 | self.queue_event(cls(src_path))
163 | elif event.is_delete_self:
164 | cls = DirDeletedEvent if event.is_directory else FileDeletedEvent
165 | self.queue_event(cls(src_path))
166 | elif event.is_delete or event.is_moved_from:
167 | cls = DirDeletedEvent if event.is_directory else FileDeletedEvent
168 | self.queue_event(cls(src_path))
169 | self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
170 | elif event.is_create:
171 | cls = DirCreatedEvent if event.is_directory else FileCreatedEvent
172 | self.queue_event(cls(src_path))
173 | self.queue_event(DirModifiedEvent(os.path.dirname(src_path)))
174 |
175 |
176 | class InotifyObserver(BaseObserver):
177 | """
178 | Observer thread that schedules watching directories and dispatches
179 | calls to event handlers.
180 | """
181 |
182 | def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT):
183 | BaseObserver.__init__(self, emitter_class=InotifyEmitter,
184 | timeout=timeout)
185 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/observers/inotify_buffer.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright 2014 Thomas Amland
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | import time
18 | import logging
19 | import threading
20 | from collections import deque
21 | from watchdog.utils import DaemonThread
22 | from .inotify_c import Inotify
23 |
24 | STOP_EVENT = object()
25 |
26 |
27 | class _Worker(DaemonThread):
28 | """
29 | Thread that reads events from `inotify` and writes to `queue`.
30 | """
31 |
32 | def __init__(self, inotify, queue):
33 | DaemonThread.__init__(self)
34 | self._read_events = inotify.read_events
35 | self._queue = queue
36 |
37 | def run(self):
38 | while self.should_keep_running():
39 | inotify_events = self._read_events()
40 | for inotify_event in inotify_events:
41 | logging.debug("worker: in event %s", inotify_event)
42 | if inotify_event.is_moved_to:
43 | from_event = self._queue._catch(inotify_event.cookie)
44 | if from_event:
45 | self._queue._put((from_event, inotify_event))
46 | else:
47 | logging.debug("worker: could not find maching move_from event")
48 | self._queue._put(inotify_event)
49 | else:
50 | self._queue._put(inotify_event)
51 |
52 |
53 | class InotifyBuffer(object):
54 | """
55 | A wrapper for `Inotify` that keeps events in memory for `delay` seconds.
56 | IN_MOVED_FROM and IN_MOVED_TO events are paired during this time.
57 | """
58 | def __init__(self, path, recursive=False):
59 | self.delay = 0.5
60 | self._lock = threading.Lock()
61 | self._not_empty = threading.Condition(self._lock)
62 | self._queue = deque()
63 | self._inotify = Inotify(path, recursive)
64 | self._worker = _Worker(self._inotify, self)
65 | self._worker.start()
66 |
67 | def read_event(self):
68 | """
69 | Returns a single event or a tuple of from/to events in case of a
70 | paired move event.
71 | """
72 | while True:
73 | # wait for queue
74 | self._not_empty.acquire()
75 | while len(self._queue) == 0:
76 | self._not_empty.wait()
77 | head, insert_time = self._queue[0]
78 | self._not_empty.release()
79 |
80 | # wait for delay
81 | time_left = insert_time + self.delay - time.time()
82 | while time_left > 0:
83 | time.sleep(time_left)
84 | time_left = insert_time + self.delay - time.time()
85 |
86 | # return if event is still here
87 | self._lock.acquire()
88 | try:
89 | if len(self._queue) > 0 and self._queue[0][0] is head:
90 | self._queue.popleft()
91 | return head
92 | finally:
93 | self._lock.release()
94 |
95 | def close(self):
96 | self._worker.stop()
97 | self._inotify.close()
98 | self._worker.join()
99 | # Add the stop event to unblock the read_event which waits for
100 | # events in the queue... even after inotify buffer is closed.
101 | self._put(STOP_EVENT)
102 |
103 | def _put(self, elem):
104 | self._lock.acquire()
105 | self._queue.append((elem, time.time()))
106 | self._not_empty.notify()
107 | self._lock.release()
108 |
109 | def _catch(self, cookie):
110 | self._lock.acquire()
111 | ret = None
112 | for i, elem in enumerate(self._queue):
113 | event, _ = elem
114 | try:
115 | if event.is_moved_from and event.cookie == cookie:
116 | ret = event
117 | del self._queue[i]
118 | break
119 | except AttributeError:
120 | pass
121 | self._lock.release()
122 | return ret
123 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/observers/polling.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 |
20 | """
21 | :module: watchdog.observers.polling
22 | :synopsis: Polling emitter implementation.
23 | :author: yesudeep@google.com (Yesudeep Mangalapilly)
24 |
25 | Classes
26 | -------
27 | .. autoclass:: PollingObserver
28 | :members:
29 | :show-inheritance:
30 |
31 | .. autoclass:: PollingObserverVFS
32 | :members:
33 | :show-inheritance:
34 | :special-members:
35 | """
36 |
37 | from __future__ import with_statement
38 | import os
39 | import threading
40 | from functools import partial
41 | from watchdog.utils import stat as default_stat
42 | from watchdog.utils.dirsnapshot import DirectorySnapshot, DirectorySnapshotDiff
43 | from watchdog.observers.api import (
44 | EventEmitter,
45 | BaseObserver,
46 | DEFAULT_OBSERVER_TIMEOUT,
47 | DEFAULT_EMITTER_TIMEOUT
48 | )
49 |
50 | from watchdog.events import (
51 | DirMovedEvent,
52 | DirDeletedEvent,
53 | DirCreatedEvent,
54 | DirModifiedEvent,
55 | FileMovedEvent,
56 | FileDeletedEvent,
57 | FileCreatedEvent,
58 | FileModifiedEvent
59 | )
60 |
61 |
62 | class PollingEmitter(EventEmitter):
63 | """
64 | Platform-independent emitter that polls a directory to detect file
65 | system changes.
66 | """
67 |
68 | def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT,
69 | stat=default_stat, listdir=os.listdir):
70 | EventEmitter.__init__(self, event_queue, watch, timeout)
71 | self._snapshot = None
72 | self._lock = threading.Lock()
73 | self._take_snapshot = lambda: DirectorySnapshot(
74 | self.watch.path, self.watch.is_recursive, stat=stat, listdir=listdir)
75 |
76 | def queue_events(self, timeout):
77 | if not self._snapshot:
78 | self._snapshot = self._take_snapshot()
79 |
80 | # We don't want to hit the disk continuously.
81 | # timeout behaves like an interval for polling emitters.
82 | if self.stopped_event.wait(timeout):
83 | return
84 |
85 | with self._lock:
86 | if not self.should_keep_running():
87 | return
88 |
89 | # Get event diff between fresh snapshot and previous snapshot.
90 | # Update snapshot.
91 | new_snapshot = self._take_snapshot()
92 | events = DirectorySnapshotDiff(self._snapshot, new_snapshot)
93 | self._snapshot = new_snapshot
94 |
95 | # Files.
96 | for src_path in events.files_deleted:
97 | self.queue_event(FileDeletedEvent(src_path))
98 | for src_path in events.files_modified:
99 | self.queue_event(FileModifiedEvent(src_path))
100 | for src_path in events.files_created:
101 | self.queue_event(FileCreatedEvent(src_path))
102 | for src_path, dest_path in events.files_moved:
103 | self.queue_event(FileMovedEvent(src_path, dest_path))
104 |
105 | # Directories.
106 | for src_path in events.dirs_deleted:
107 | self.queue_event(DirDeletedEvent(src_path))
108 | for src_path in events.dirs_modified:
109 | self.queue_event(DirModifiedEvent(src_path))
110 | for src_path in events.dirs_created:
111 | self.queue_event(DirCreatedEvent(src_path))
112 | for src_path, dest_path in events.dirs_moved:
113 | self.queue_event(DirMovedEvent(src_path, dest_path))
114 |
115 |
116 | class PollingObserver(BaseObserver):
117 | """
118 | Platform-independent observer that polls a directory to detect file
119 | system changes.
120 | """
121 |
122 | def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT):
123 | BaseObserver.__init__(self, emitter_class=PollingEmitter, timeout=timeout)
124 |
125 |
126 | class PollingObserverVFS(BaseObserver):
127 | """
128 | File system independent observer that polls a directory to detect changes.
129 | """
130 |
131 | def __init__(self, stat, listdir, polling_interval=1):
132 | """
133 | :param stat: stat function. See ``os.stat`` for details.
134 | :param listdir: listdir function. See ``os.listdir`` for details.
135 | :type polling_interval: float
136 | :param polling_interval: interval in seconds between polling the file system.
137 | """
138 | emitter_cls = partial(PollingEmitter, stat=stat, listdir=listdir)
139 | BaseObserver.__init__(self, emitter_class=emitter_cls, timeout=polling_interval)
140 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/observers/read_directory_changes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | # Copyright 2014 Thomas Amland
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # http://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
19 |
20 | from __future__ import with_statement
21 |
22 | import ctypes
23 | import threading
24 | import os.path
25 | import time
26 |
27 | from watchdog.events import (
28 | DirCreatedEvent,
29 | DirDeletedEvent,
30 | DirMovedEvent,
31 | DirModifiedEvent,
32 | FileCreatedEvent,
33 | FileDeletedEvent,
34 | FileMovedEvent,
35 | FileModifiedEvent,
36 | generate_sub_moved_events,
37 | generate_sub_created_events,
38 | )
39 |
40 | from watchdog.observers.api import (
41 | EventEmitter,
42 | BaseObserver,
43 | DEFAULT_OBSERVER_TIMEOUT,
44 | DEFAULT_EMITTER_TIMEOUT
45 | )
46 |
47 | from watchdog.observers.winapi import (
48 | read_events,
49 | get_directory_handle,
50 | close_directory_handle,
51 | )
52 |
53 |
54 | # HACK:
55 | WATCHDOG_TRAVERSE_MOVED_DIR_DELAY = 1 # seconds
56 |
57 |
58 | class WindowsApiEmitter(EventEmitter):
59 | """
60 | Windows API-based emitter that uses ReadDirectoryChangesW
61 | to detect file system changes for a watch.
62 | """
63 |
64 | def __init__(self, event_queue, watch, timeout=DEFAULT_EMITTER_TIMEOUT):
65 | EventEmitter.__init__(self, event_queue, watch, timeout)
66 | self._lock = threading.Lock()
67 | self._handle = get_directory_handle(watch.path)
68 |
69 | def on_thread_stop(self):
70 | close_directory_handle(self._handle)
71 |
72 | def queue_events(self, timeout):
73 | winapi_events = read_events(self._handle, self.watch.is_recursive)
74 | with self._lock:
75 | last_renamed_src_path = ""
76 | for winapi_event in winapi_events:
77 | src_path = os.path.join(self.watch.path, winapi_event.src_path)
78 |
79 | if winapi_event.is_renamed_old:
80 | last_renamed_src_path = src_path
81 | elif winapi_event.is_renamed_new:
82 | dest_path = src_path
83 | src_path = last_renamed_src_path
84 | if os.path.isdir(dest_path):
85 | event = DirMovedEvent(src_path, dest_path)
86 | if self.watch.is_recursive:
87 | # HACK: We introduce a forced delay before
88 | # traversing the moved directory. This will read
89 | # only file movement that finishes within this
90 | # delay time.
91 | time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
92 | # The following block of code may not
93 | # obtain moved events for the entire tree if
94 | # the I/O is not completed within the above
95 | # delay time. So, it's not guaranteed to work.
96 | # TODO: Come up with a better solution, possibly
97 | # a way to wait for I/O to complete before
98 | # queuing events.
99 | for sub_moved_event in generate_sub_moved_events(src_path, dest_path):
100 | self.queue_event(sub_moved_event)
101 | self.queue_event(event)
102 | else:
103 | self.queue_event(FileMovedEvent(src_path, dest_path))
104 | elif winapi_event.is_modified:
105 | cls = DirModifiedEvent if os.path.isdir(src_path) else FileModifiedEvent
106 | self.queue_event(cls(src_path))
107 | elif winapi_event.is_added:
108 | isdir = os.path.isdir(src_path)
109 | cls = DirCreatedEvent if isdir else FileCreatedEvent
110 | self.queue_event(cls(src_path))
111 | if isdir:
112 | # If a directory is moved from outside the watched folder to inside it
113 | # we only get a created directory event out of it, not any events for its children
114 | # so use the same hack as for file moves to get the child events
115 | time.sleep(WATCHDOG_TRAVERSE_MOVED_DIR_DELAY)
116 | sub_events = generate_sub_created_events(src_path)
117 | for sub_created_event in sub_events:
118 | self.queue_event(sub_created_event)
119 | elif winapi_event.is_removed:
120 | self.queue_event(FileDeletedEvent(src_path))
121 |
122 |
123 | class WindowsApiObserver(BaseObserver):
124 | """
125 | Observer thread that schedules watching directories and dispatches
126 | calls to event handlers.
127 | """
128 |
129 | def __init__(self, timeout=DEFAULT_OBSERVER_TIMEOUT):
130 | BaseObserver.__init__(self, emitter_class=WindowsApiEmitter,
131 | timeout=timeout)
132 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/tricks/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 |
20 | import os
21 | import signal
22 | import subprocess
23 | import time
24 |
25 | from watchdog.utils import echo, has_attribute
26 | from watchdog.events import PatternMatchingEventHandler
27 |
28 |
29 | class Trick(PatternMatchingEventHandler):
30 |
31 | """Your tricks should subclass this class."""
32 |
33 | @classmethod
34 | def generate_yaml(cls):
35 | context = dict(module_name=cls.__module__,
36 | klass_name=cls.__name__)
37 | template_yaml = """- %(module_name)s.%(klass_name)s:
38 | args:
39 | - argument1
40 | - argument2
41 | kwargs:
42 | patterns:
43 | - "*.py"
44 | - "*.js"
45 | ignore_patterns:
46 | - "version.py"
47 | ignore_directories: false
48 | """
49 | return template_yaml % context
50 |
51 |
52 | class LoggerTrick(Trick):
53 |
54 | """A simple trick that does only logs events."""
55 |
56 | def on_any_event(self, event):
57 | pass
58 |
59 | @echo.echo
60 | def on_modified(self, event):
61 | pass
62 |
63 | @echo.echo
64 | def on_deleted(self, event):
65 | pass
66 |
67 | @echo.echo
68 | def on_created(self, event):
69 | pass
70 |
71 | @echo.echo
72 | def on_moved(self, event):
73 | pass
74 |
75 |
76 | class ShellCommandTrick(Trick):
77 |
78 | """Executes shell commands in response to matched events."""
79 |
80 | def __init__(self, shell_command=None, patterns=None, ignore_patterns=None,
81 | ignore_directories=False, wait_for_process=False,
82 | drop_during_process=False):
83 | super(ShellCommandTrick, self).__init__(patterns, ignore_patterns,
84 | ignore_directories)
85 | self.shell_command = shell_command
86 | self.wait_for_process = wait_for_process
87 | self.drop_during_process = drop_during_process
88 | self.process = None
89 |
90 | def on_any_event(self, event):
91 | from string import Template
92 |
93 | if self.drop_during_process and self.process and self.process.poll() is None:
94 | return
95 |
96 | if event.is_directory:
97 | object_type = 'directory'
98 | else:
99 | object_type = 'file'
100 |
101 | context = {
102 | 'watch_src_path': event.src_path,
103 | 'watch_dest_path': '',
104 | 'watch_event_type': event.event_type,
105 | 'watch_object': object_type,
106 | }
107 |
108 | if self.shell_command is None:
109 | if has_attribute(event, 'dest_path'):
110 | context.update({'dest_path': event.dest_path})
111 | command = 'echo "${watch_event_type} ${watch_object} from ${watch_src_path} to ${watch_dest_path}"'
112 | else:
113 | command = 'echo "${watch_event_type} ${watch_object} ${watch_src_path}"'
114 | else:
115 | if has_attribute(event, 'dest_path'):
116 | context.update({'watch_dest_path': event.dest_path})
117 | command = self.shell_command
118 |
119 | command = Template(command).safe_substitute(**context)
120 | self.process = subprocess.Popen(command, shell=True)
121 | if self.wait_for_process:
122 | self.process.wait()
123 |
124 |
125 | class AutoRestartTrick(Trick):
126 |
127 | """Starts a long-running subprocess and restarts it on matched events.
128 |
129 | The command parameter is a list of command arguments, such as
130 | ['bin/myserver', '-c', 'etc/myconfig.ini'].
131 |
132 | Call start() after creating the Trick. Call stop() when stopping
133 | the process.
134 | """
135 |
136 | def __init__(self, command, patterns=None, ignore_patterns=None,
137 | ignore_directories=False, stop_signal=signal.SIGINT,
138 | kill_after=10):
139 | super(AutoRestartTrick, self).__init__(
140 | patterns, ignore_patterns, ignore_directories)
141 | self.command = ['setsid'] + command
142 | self.stop_signal = stop_signal
143 | self.kill_after = kill_after
144 | self.process = None
145 |
146 | def start(self):
147 | self.process = subprocess.Popen(self.command)
148 |
149 | def stop(self):
150 | if self.process is None:
151 | return
152 | try:
153 | os.killpg(os.getpgid(self.process.pid), self.stop_signal)
154 | except OSError:
155 | # Process is already gone
156 | pass
157 | else:
158 | kill_time = time.time() + self.kill_after
159 | while time.time() < kill_time:
160 | if self.process.poll() is not None:
161 | break
162 | time.sleep(0.25)
163 | else:
164 | try:
165 | os.killpg(os.getpgid(self.process.pid), 9)
166 | except OSError:
167 | # Process is already gone
168 | pass
169 | self.process = None
170 |
171 | @echo.echo
172 | def on_any_event(self, event):
173 | self.stop()
174 | self.start()
175 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 |
20 | """
21 | :module: watchdog.utils
22 | :synopsis: Utility classes and functions.
23 | :author: yesudeep@google.com (Yesudeep Mangalapilly)
24 |
25 | Classes
26 | -------
27 | .. autoclass:: DaemonThread
28 | :members:
29 | :show-inheritance:
30 | :inherited-members:
31 |
32 | """
33 | import os
34 | import sys
35 | import threading
36 | import watchdog.utils.platform
37 | from collections import namedtuple
38 |
39 |
40 | if sys.version_info[0] == 2 and platform.is_windows():
41 | # st_ino is not implemented in os.stat on this platform
42 | import win32stat
43 | stat = win32stat.stat
44 | else:
45 | stat = os.stat
46 |
47 |
48 | def ctypes_find_library(name, default):
49 | """Finds a dynamic library."""
50 | try:
51 | import ctypes.util
52 | except ImportError:
53 | raise RuntimeError('ctypes not available on this system')
54 | module_path = None
55 | try:
56 | module_path = ctypes.util.find_library(name)
57 | except (OSError, IOError):
58 | module_path = default
59 | return module_path
60 |
61 |
62 | def has_attribute(ob, attribute):
63 | """
64 | :func:`hasattr` swallows exceptions. :func:`has_attribute` tests a Python object for the
65 | presence of an attribute.
66 |
67 | :param ob:
68 | object to inspect
69 | :param attribute:
70 | ``str`` for the name of the attribute.
71 | """
72 | return getattr(ob, attribute, None) is not None
73 |
74 |
75 | class DaemonThread(threading.Thread):
76 |
77 | """
78 | Daemon thread convenience class, sets a few properties and makes
79 | writing daemon threads a little easier.
80 | """
81 |
82 | def __init__(self):
83 | threading.Thread.__init__(self)
84 | if has_attribute(self, 'daemon'):
85 | self.daemon = True
86 | else:
87 | self.setDaemon(True)
88 | self._stopped_event = threading.Event()
89 |
90 | if not has_attribute(self._stopped_event, 'is_set'):
91 | self._stopped_event.is_set = self._stopped_event.isSet
92 |
93 | @property
94 | def stopped_event(self):
95 | return self._stopped_event
96 |
97 | def should_keep_running(self):
98 | """Determines whether the daemon thread should continue running."""
99 | return not self._stopped_event.is_set()
100 |
101 | def on_thread_stop(self):
102 | """Override this method instead of :meth:`stop()`.
103 | :meth:`stop()` calls this method.
104 |
105 | Note that this method is called immediately after the daemon thread
106 | is signaled to halt.
107 | """
108 | pass
109 |
110 | def stop(self):
111 | """Signals the daemon thread to stop."""
112 | self._stopped_event.set()
113 | self.on_thread_stop()
114 |
115 |
116 | def load_module(module_name):
117 | """Imports a module given its name and returns a handle to it."""
118 | try:
119 | __import__(module_name)
120 | except ImportError:
121 | raise ImportError('No module named %s' % module_name)
122 | return sys.modules[module_name]
123 |
124 |
125 | def load_class(dotted_path):
126 | """Loads and returns a class definition provided a dotted path
127 | specification the last part of the dotted path is the class name
128 | and there is at least one module name preceding the class name.
129 |
130 | Notes:
131 | You will need to ensure that the module you are trying to load
132 | exists in the Python path.
133 |
134 | Examples:
135 | - module.name.ClassName # Provided module.name is in the Python path.
136 | - module.ClassName # Provided module is in the Python path.
137 |
138 | What won't work:
139 | - ClassName
140 | - modle.name.ClassName # Typo in module name.
141 | - module.name.ClasNam # Typo in classname.
142 | """
143 | dotted_path_split = dotted_path.split('.')
144 | if len(dotted_path_split) > 1:
145 | klass_name = dotted_path_split[-1]
146 | module_name = '.'.join(dotted_path_split[:-1])
147 |
148 | module = load_module(module_name)
149 | if has_attribute(module, klass_name):
150 | klass = getattr(module, klass_name)
151 | return klass
152 | # Finally create and return an instance of the class
153 | # return klass(*args, **kwargs)
154 | else:
155 | raise AttributeError('Module %s does not have class attribute %s' % (
156 | module_name, klass_name))
157 | else:
158 | raise ValueError(
159 | 'Dotted module path %s must contain a module name and a classname' % dotted_path)
160 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/bricks.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 |
20 | """
21 | Utility collections or "bricks".
22 |
23 | :module: watchdog.utils.bricks
24 | :author: yesudeep@google.com (Yesudeep Mangalapilly)
25 | :author: lalinsky@gmail.com (Lukáš Lalinský)
26 | :author: python@rcn.com (Raymond Hettinger)
27 |
28 | Classes
29 | =======
30 | .. autoclass:: OrderedSetQueue
31 | :members:
32 | :show-inheritance:
33 | :inherited-members:
34 |
35 | .. autoclass:: OrderedSet
36 |
37 | """
38 |
39 | import sys
40 | import collections
41 | from .compat import queue
42 |
43 | class SkipRepeatsQueue(queue.Queue):
44 |
45 | """Thread-safe implementation of an special queue where a
46 | put of the last-item put'd will be dropped.
47 |
48 | The implementation leverages locking already implemented in the base class
49 | redefining only the primitives.
50 |
51 | Queued items must be immutable and hashable so that they can be used
52 | as dictionary keys. You must implement **only read-only properties** and
53 | the :meth:`Item.__hash__()`, :meth:`Item.__eq__()`, and
54 | :meth:`Item.__ne__()` methods for items to be hashable.
55 |
56 | An example implementation follows::
57 |
58 | class Item(object):
59 | def __init__(self, a, b):
60 | self._a = a
61 | self._b = b
62 |
63 | @property
64 | def a(self):
65 | return self._a
66 |
67 | @property
68 | def b(self):
69 | return self._b
70 |
71 | def _key(self):
72 | return (self._a, self._b)
73 |
74 | def __eq__(self, item):
75 | return self._key() == item._key()
76 |
77 | def __ne__(self, item):
78 | return self._key() != item._key()
79 |
80 | def __hash__(self):
81 | return hash(self._key())
82 |
83 | based on the OrderedSetQueue below
84 | """
85 |
86 | def _init(self, maxsize):
87 | queue.Queue._init(self, maxsize)
88 | self._last_item = None
89 |
90 | def _put(self, item):
91 | if item != self._last_item:
92 | queue.Queue._put(self, item)
93 | self._last_item = item
94 | else:
95 | # `put` increments `unfinished_tasks` even if we did not put
96 | # anything into the queue here
97 | self.unfinished_tasks -= 1
98 |
99 | def _get(self):
100 | item = queue.Queue._get(self)
101 | if item is self._last_item:
102 | self._last_item = None
103 | return item
104 |
105 |
106 | class OrderedSetQueue(queue.Queue):
107 |
108 | """Thread-safe implementation of an ordered set queue.
109 |
110 | Disallows adding a duplicate item while maintaining the
111 | order of items in the queue. The implementation leverages
112 | locking already implemented in the base class
113 | redefining only the primitives. Since the internal queue
114 | is not replaced, the order is maintained. The set is used
115 | merely to check for the existence of an item.
116 |
117 | Queued items must be immutable and hashable so that they can be used
118 | as dictionary keys. You must implement **only read-only properties** and
119 | the :meth:`Item.__hash__()`, :meth:`Item.__eq__()`, and
120 | :meth:`Item.__ne__()` methods for items to be hashable.
121 |
122 | An example implementation follows::
123 |
124 | class Item(object):
125 | def __init__(self, a, b):
126 | self._a = a
127 | self._b = b
128 |
129 | @property
130 | def a(self):
131 | return self._a
132 |
133 | @property
134 | def b(self):
135 | return self._b
136 |
137 | def _key(self):
138 | return (self._a, self._b)
139 |
140 | def __eq__(self, item):
141 | return self._key() == item._key()
142 |
143 | def __ne__(self, item):
144 | return self._key() != item._key()
145 |
146 | def __hash__(self):
147 | return hash(self._key())
148 |
149 | :author: lalinsky@gmail.com (Lukáš Lalinský)
150 | :url: http://stackoverflow.com/questions/1581895/how-check-if-a-task-is-already-in-python-queue
151 | """
152 |
153 | def _init(self, maxsize):
154 | queue.Queue._init(self, maxsize)
155 | self._set_of_items = set()
156 |
157 | def _put(self, item):
158 | if item not in self._set_of_items:
159 | queue.Queue._put(self, item)
160 | self._set_of_items.add(item)
161 | else:
162 | # `put` increments `unfinished_tasks` even if we did not put
163 | # anything into the queue here
164 | self.unfinished_tasks -= 1
165 |
166 | def _get(self):
167 | item = queue.Queue._get(self)
168 | self._set_of_items.remove(item)
169 | return item
170 |
171 |
172 | if sys.version_info >= (2, 6, 0):
173 | KEY, PREV, NEXT = list(range(3))
174 |
175 | class OrderedSet(collections.MutableSet):
176 |
177 | """
178 | Implementation based on a doubly-linked link and an internal dictionary.
179 | This design gives :class:`OrderedSet` the same big-Oh running times as
180 | regular sets including O(1) adds, removes, and lookups as well as
181 | O(n) iteration.
182 |
183 | .. ADMONITION:: Implementation notes
184 |
185 | Runs on Python 2.6 or later (and runs on Python 3.0 or later
186 | without any modifications).
187 |
188 | :author: python@rcn.com (Raymond Hettinger)
189 | :url: http://code.activestate.com/recipes/576694/
190 | """
191 |
192 | def __init__(self, iterable=None):
193 | self.end = end = []
194 | end += [None, end, end] # sentinel node for doubly linked list
195 | self.map = {} # key --> [key, prev, next]
196 | if iterable is not None:
197 | self |= iterable
198 |
199 | def __len__(self):
200 | return len(self.map)
201 |
202 | def __contains__(self, key):
203 | return key in self.map
204 |
205 | def add(self, key):
206 | if key not in self.map:
207 | end = self.end
208 | curr = end[PREV]
209 | curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
210 |
211 | def discard(self, key):
212 | if key in self.map:
213 | key, prev, _next = self.map.pop(key)
214 | prev[NEXT] = _next
215 | _next[PREV] = prev
216 |
217 | def __iter__(self):
218 | end = self.end
219 | curr = end[NEXT]
220 | while curr is not end:
221 | yield curr[KEY]
222 | curr = curr[NEXT]
223 |
224 | def __reversed__(self):
225 | end = self.end
226 | curr = end[PREV]
227 | while curr is not end:
228 | yield curr[KEY]
229 | curr = curr[PREV]
230 |
231 | def pop(self, last=True):
232 | if not self:
233 | raise KeyError('set is empty')
234 | key = next(reversed(self)) if last else next(iter(self))
235 | self.discard(key)
236 | return key
237 |
238 | def __repr__(self):
239 | if not self:
240 | return '%s()' % (self.__class__.__name__,)
241 | return '%s(%r)' % (self.__class__.__name__, list(self))
242 |
243 | def __eq__(self, other):
244 | if isinstance(other, OrderedSet):
245 | return len(self) == len(other) and list(self) == list(other)
246 | return set(self) == set(other)
247 |
248 | def __del__(self):
249 | self.clear() # remove circular references
250 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/compat.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright 2014 Thomas Amland
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | try:
18 | import queue
19 | except ImportError:
20 | import Queue as queue
21 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/decorators.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # Most of this code was obtained from the Python documentation online.
4 |
5 | """Decorator utility functions.
6 |
7 | decorators:
8 | - synchronized
9 | - propertyx
10 | - accepts
11 | - returns
12 | - singleton
13 | - attrs
14 | - deprecated
15 | """
16 |
17 | import functools
18 | import warnings
19 | import threading
20 | import sys
21 |
22 |
23 | def synchronized(lock=None):
24 | """Decorator that synchronizes a method or a function with a mutex lock.
25 |
26 | Example usage:
27 |
28 | @synchronized()
29 | def operation(self, a, b):
30 | ...
31 | """
32 | if lock is None:
33 | lock = threading.Lock()
34 |
35 | def wrapper(function):
36 | def new_function(*args, **kwargs):
37 | lock.acquire()
38 | try:
39 | return function(*args, **kwargs)
40 | finally:
41 | lock.release()
42 |
43 | return new_function
44 |
45 | return wrapper
46 |
47 |
48 | def propertyx(function):
49 | """Decorator to easily create properties in classes.
50 |
51 | Example:
52 |
53 | class Angle(object):
54 | def __init__(self, rad):
55 | self._rad = rad
56 |
57 | @property
58 | def rad():
59 | def fget(self):
60 | return self._rad
61 | def fset(self, angle):
62 | if isinstance(angle, Angle):
63 | angle = angle.rad
64 | self._rad = float(angle)
65 |
66 | Arguments:
67 | - `function`: The function to be decorated.
68 | """
69 | keys = ('fget', 'fset', 'fdel')
70 | func_locals = {'doc': function.__doc__}
71 |
72 | def probe_func(frame, event, arg):
73 | if event == 'return':
74 | locals = frame.f_locals
75 | func_locals.update(dict((k, locals.get(k)) for k in keys))
76 | sys.settrace(None)
77 | return probe_func
78 |
79 | sys.settrace(probe_func)
80 | function()
81 | return property(**func_locals)
82 |
83 |
84 | def accepts(*types):
85 | """Decorator to ensure that the decorated function accepts the given types as arguments.
86 |
87 | Example:
88 | @accepts(int, (int,float))
89 | @returns((int,float))
90 | def func(arg1, arg2):
91 | return arg1 * arg2
92 | """
93 |
94 | def check_accepts(f):
95 | assert len(types) == f.__code__.co_argcount
96 |
97 | def new_f(*args, **kwds):
98 | for (a, t) in zip(args, types):
99 | assert isinstance(a, t),\
100 | "arg %r does not match %s" % (a, t)
101 | return f(*args, **kwds)
102 |
103 | new_f.__name__ = f.__name__
104 | return new_f
105 |
106 | return check_accepts
107 |
108 |
109 | def returns(rtype):
110 | """Decorator to ensure that the decorated function returns the given
111 | type as argument.
112 |
113 | Example:
114 | @accepts(int, (int,float))
115 | @returns((int,float))
116 | def func(arg1, arg2):
117 | return arg1 * arg2
118 | """
119 |
120 | def check_returns(f):
121 | def new_f(*args, **kwds):
122 | result = f(*args, **kwds)
123 | assert isinstance(result, rtype),\
124 | "return value %r does not match %s" % (result, rtype)
125 | return result
126 |
127 | new_f.__name__ = f.__name__
128 | return new_f
129 |
130 | return check_returns
131 |
132 |
133 | def singleton(cls):
134 | """Decorator to ensures a class follows the singleton pattern.
135 |
136 | Example:
137 | @singleton
138 | class MyClass:
139 | ...
140 | """
141 | instances = {}
142 |
143 | def getinstance():
144 | if cls not in instances:
145 | instances[cls] = cls()
146 | return instances[cls]
147 |
148 | return getinstance
149 |
150 |
151 | def attrs(**kwds):
152 | """Decorator to add attributes to a function.
153 |
154 | Example:
155 |
156 | @attrs(versionadded="2.2",
157 | author="Guido van Rossum")
158 | def mymethod(f):
159 | ...
160 | """
161 |
162 | def decorate(f):
163 | for k in kwds:
164 | setattr(f, k, kwds[k])
165 | return f
166 |
167 | return decorate
168 |
169 |
170 | def deprecated(func):
171 | """This is a decorator which can be used to mark functions
172 | as deprecated. It will result in a warning being emitted
173 | when the function is used.
174 |
175 | ## Usage examples ##
176 | @deprecated
177 | def my_func():
178 | pass
179 |
180 | @other_decorators_must_be_upper
181 | @deprecated
182 | def my_func():
183 | pass
184 | """
185 |
186 | @functools.wraps(func)
187 | def new_func(*args, **kwargs):
188 | warnings.warn_explicit(
189 | "Call to deprecated function %(funcname)s." % {
190 | 'funcname': func.__name__,
191 | },
192 | category=DeprecationWarning,
193 | filename=func.__code__.co_filename,
194 | lineno=func.__code__.co_firstlineno + 1
195 | )
196 | return func(*args, **kwargs)
197 |
198 | return new_func
199 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/dirsnapshot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | # Copyright 2014 Thomas Amland
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 | # you may not use this file except in compliance with the License.
10 | # You may obtain a copy of the License at
11 | #
12 | # http://www.apache.org/licenses/LICENSE-2.0
13 | #
14 | # Unless required by applicable law or agreed to in writing, software
15 | # distributed under the License is distributed on an "AS IS" BASIS,
16 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | # See the License for the specific language governing permissions and
18 | # limitations under the License.
19 |
20 | """
21 | :module: watchdog.utils.dirsnapshot
22 | :synopsis: Directory snapshots and comparison.
23 | :author: yesudeep@google.com (Yesudeep Mangalapilly)
24 |
25 | .. ADMONITION:: Where are the moved events? They "disappeared"
26 |
27 | This implementation does not take partition boundaries
28 | into consideration. It will only work when the directory
29 | tree is entirely on the same file system. More specifically,
30 | any part of the code that depends on inode numbers can
31 | break if partition boundaries are crossed. In these cases,
32 | the snapshot diff will represent file/directory movement as
33 | created and deleted events.
34 |
35 | Classes
36 | -------
37 | .. autoclass:: DirectorySnapshot
38 | :members:
39 | :show-inheritance:
40 |
41 | .. autoclass:: DirectorySnapshotDiff
42 | :members:
43 | :show-inheritance:
44 |
45 | """
46 |
47 | import os
48 | from stat import S_ISDIR
49 | from watchdog.utils import platform
50 | from watchdog.utils import stat as default_stat
51 |
52 |
53 | class DirectorySnapshotDiff(object):
54 | """
55 | Compares two directory snapshots and creates an object that represents
56 | the difference between the two snapshots.
57 |
58 | :param ref:
59 | The reference directory snapshot.
60 | :type ref:
61 | :class:`DirectorySnapshot`
62 | :param snapshot:
63 | The directory snapshot which will be compared
64 | with the reference snapshot.
65 | :type snapshot:
66 | :class:`DirectorySnapshot`
67 | """
68 |
69 | def __init__(self, ref, snapshot):
70 | created = snapshot.paths - ref.paths
71 | deleted = ref.paths - snapshot.paths
72 |
73 | # check that all unchanged paths have the same inode
74 | for path in ref.paths & snapshot.paths:
75 | if ref.inode(path) != snapshot.inode(path):
76 | created.add(path)
77 | deleted.add(path)
78 |
79 | # find moved paths
80 | moved = set()
81 | for path in set(deleted):
82 | inode = ref.inode(path)
83 | new_path = snapshot.path(inode)
84 | if new_path:
85 | # file is not deleted but moved
86 | deleted.remove(path)
87 | moved.add((path, new_path))
88 |
89 | for path in set(created):
90 | inode = snapshot.inode(path)
91 | old_path = ref.path(inode)
92 | if old_path:
93 | created.remove(path)
94 | moved.add((old_path, path))
95 |
96 | # find modified paths
97 | # first check paths that have not moved
98 | modified = set()
99 | for path in ref.paths & snapshot.paths:
100 | if ref.inode(path) == snapshot.inode(path):
101 | if ref.mtime(path) != snapshot.mtime(path):
102 | modified.add(path)
103 |
104 | for (old_path, new_path) in moved:
105 | if ref.mtime(old_path) != snapshot.mtime(new_path):
106 | modified.add(old_path)
107 |
108 | self._dirs_created = [path for path in created if snapshot.isdir(path)]
109 | self._dirs_deleted = [path for path in deleted if ref.isdir(path)]
110 | self._dirs_modified = [path for path in modified if ref.isdir(path)]
111 | self._dirs_moved = [(frm, to) for (frm, to) in moved if ref.isdir(frm)]
112 |
113 | self._files_created = list(created - set(self._dirs_created))
114 | self._files_deleted = list(deleted - set(self._dirs_deleted))
115 | self._files_modified = list(modified - set(self._dirs_modified))
116 | self._files_moved = list(moved - set(self._dirs_moved))
117 |
118 | @property
119 | def files_created(self):
120 | """List of files that were created."""
121 | return self._files_created
122 |
123 | @property
124 | def files_deleted(self):
125 | """List of files that were deleted."""
126 | return self._files_deleted
127 |
128 | @property
129 | def files_modified(self):
130 | """List of files that were modified."""
131 | return self._files_modified
132 |
133 | @property
134 | def files_moved(self):
135 | """
136 | List of files that were moved.
137 |
138 | Each event is a two-tuple the first item of which is the path
139 | that has been renamed to the second item in the tuple.
140 | """
141 | return self._files_moved
142 |
143 | @property
144 | def dirs_modified(self):
145 | """
146 | List of directories that were modified.
147 | """
148 | return self._dirs_modified
149 |
150 | @property
151 | def dirs_moved(self):
152 | """
153 | List of directories that were moved.
154 |
155 | Each event is a two-tuple the first item of which is the path
156 | that has been renamed to the second item in the tuple.
157 | """
158 | return self._dirs_moved
159 |
160 | @property
161 | def dirs_deleted(self):
162 | """
163 | List of directories that were deleted.
164 | """
165 | return self._dirs_deleted
166 |
167 | @property
168 | def dirs_created(self):
169 | """
170 | List of directories that were created.
171 | """
172 | return self._dirs_created
173 |
174 | class DirectorySnapshot(object):
175 | """
176 | A snapshot of stat information of files in a directory.
177 |
178 | :param path:
179 | The directory path for which a snapshot should be taken.
180 | :type path:
181 | ``str``
182 | :param recursive:
183 | ``True`` if the entire directory tree should be included in the
184 | snapshot; ``False`` otherwise.
185 | :type recursive:
186 | ``bool``
187 | :param walker_callback:
188 | .. deprecated:: 0.7.2
189 | :param stat:
190 | Use custom stat function that returns a stat structure for path.
191 | Currently only st_dev, st_ino, st_mode and st_mtime are needed.
192 |
193 | A function with the signature ``walker_callback(path, stat_info)``
194 | which will be called for every entry in the directory tree.
195 | :param listdir:
196 | Use custom listdir function. See ``os.listdir`` for details.
197 | """
198 |
199 | def __init__(self, path, recursive=True,
200 | walker_callback=(lambda p, s: None),
201 | stat=default_stat,
202 | listdir=os.listdir):
203 | self._stat_info = {}
204 | self._inode_to_path = {}
205 |
206 | st = stat(path)
207 | self._stat_info[path] = st
208 | self._inode_to_path[(st.st_ino, st.st_dev)] = path
209 |
210 | def walk(root):
211 | paths = [os.path.join(root, name) for name in listdir(root)]
212 | entries = []
213 | for p in paths:
214 | try:
215 | entries.append((p, stat(p)))
216 | except OSError:
217 | continue
218 | for _ in entries:
219 | yield _
220 | if recursive:
221 | for path, st in entries:
222 | if S_ISDIR(st.st_mode):
223 | for _ in walk(path):
224 | yield _
225 |
226 | for p, st in walk(path):
227 | i = (st.st_ino, st.st_dev)
228 | self._inode_to_path[i] = p
229 | self._stat_info[p] = st
230 | walker_callback(p, st)
231 |
232 | @property
233 | def paths(self):
234 | """
235 | Set of file/directory paths in the snapshot.
236 | """
237 | return set(self._stat_info.keys())
238 |
239 | def path(self, id):
240 | """
241 | Returns path for id. None if id is unknown to this snapshot.
242 | """
243 | return self._inode_to_path.get(id)
244 |
245 | def inode(self, path):
246 | """ Returns an id for path. """
247 | st = self._stat_info[path]
248 | return (st.st_ino, st.st_dev)
249 |
250 | def isdir(self, path):
251 | return S_ISDIR(self._stat_info[path].st_mode)
252 |
253 | def mtime(self, path):
254 | return self._stat_info[path].st_mtime
255 |
256 | def stat_info(self, path):
257 | """
258 | Returns a stat information object for the specified path from
259 | the snapshot.
260 |
261 | Attached information is subject to change. Do not use unless
262 | you specify `stat` in constructor. Use :func:`inode`, :func:`mtime`,
263 | :func:`isdir` instead.
264 |
265 | :param path:
266 | The path for which stat information should be obtained
267 | from a snapshot.
268 | """
269 | return self._stat_info[path]
270 |
271 | def __sub__(self, previous_dirsnap):
272 | """Allow subtracting a DirectorySnapshot object instance from
273 | another.
274 |
275 | :returns:
276 | A :class:`DirectorySnapshotDiff` object.
277 | """
278 | return DirectorySnapshotDiff(previous_dirsnap, self)
279 |
280 | def __str__(self):
281 | return self.__repr__()
282 |
283 | def __repr__(self):
284 | return str(self._stat_info)
285 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/echo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # echo.py: Tracing function calls using Python decorators.
4 | #
5 | # Written by Thomas Guest
6 | # Please see http://wordaligned.org/articles/echo
7 | #
8 | # Place into the public domain.
9 |
10 | """ Echo calls made to functions and methods in a module.
11 |
12 | "Echoing" a function call means printing out the name of the function
13 | and the values of its arguments before making the call (which is more
14 | commonly referred to as "tracing", but Python already has a trace module).
15 |
16 | Example: to echo calls made to functions in "my_module" do:
17 |
18 | import echo
19 | import my_module
20 | echo.echo_module(my_module)
21 |
22 | Example: to echo calls made to functions in "my_module.my_class" do:
23 |
24 | echo.echo_class(my_module.my_class)
25 |
26 | Alternatively, echo.echo can be used to decorate functions. Calls to the
27 | decorated function will be echoed.
28 |
29 | Example:
30 |
31 | @echo.echo
32 | def my_function(args):
33 | pass
34 | """
35 | import inspect
36 | import sys
37 |
38 |
39 | def name(item):
40 | " Return an item's name. "
41 | return item.__name__
42 |
43 |
44 | def is_classmethod(instancemethod):
45 | " Determine if an instancemethod is a classmethod. "
46 | return instancemethod.__self__ is not None
47 |
48 |
49 | def is_class_private_name(name):
50 | " Determine if a name is a class private name. "
51 | # Exclude system defined names such as __init__, __add__ etc
52 | return name.startswith("__") and not name.endswith("__")
53 |
54 |
55 | def method_name(method):
56 | """ Return a method's name.
57 |
58 | This function returns the name the method is accessed by from
59 | outside the class (i.e. it prefixes "private" methods appropriately).
60 | """
61 | mname = name(method)
62 | if is_class_private_name(mname):
63 | mname = "_%s%s" % (name(method.__self__.__class__), mname)
64 | return mname
65 |
66 |
67 | def format_arg_value(arg_val):
68 | """ Return a string representing a (name, value) pair.
69 |
70 | >>> format_arg_value(('x', (1, 2, 3)))
71 | 'x=(1, 2, 3)'
72 | """
73 | arg, val = arg_val
74 | return "%s=%r" % (arg, val)
75 |
76 |
77 | def echo(fn, write=sys.stdout.write):
78 | """ Echo calls to a function.
79 |
80 | Returns a decorated version of the input function which "echoes" calls
81 | made to it by writing out the function's name and the arguments it was
82 | called with.
83 | """
84 | import functools
85 | # Unpack function's arg count, arg names, arg defaults
86 | code = fn.__code__
87 | argcount = code.co_argcount
88 | argnames = code.co_varnames[:argcount]
89 | fn_defaults = fn.__defaults__ or list()
90 | argdefs = dict(list(zip(argnames[-len(fn_defaults):], fn_defaults)))
91 |
92 | @functools.wraps(fn)
93 | def wrapped(*v, **k):
94 | # Collect function arguments by chaining together positional,
95 | # defaulted, extra positional and keyword arguments.
96 | positional = list(map(format_arg_value, list(zip(argnames, v))))
97 | defaulted = [format_arg_value((a, argdefs[a]))
98 | for a in argnames[len(v):] if a not in k]
99 | nameless = list(map(repr, v[argcount:]))
100 | keyword = list(map(format_arg_value, list(k.items())))
101 | args = positional + defaulted + nameless + keyword
102 | write("%s(%s)\n" % (name(fn), ", ".join(args)))
103 | return fn(*v, **k)
104 |
105 | return wrapped
106 |
107 |
108 | def echo_instancemethod(klass, method, write=sys.stdout.write):
109 | """ Change an instancemethod so that calls to it are echoed.
110 |
111 | Replacing a classmethod is a little more tricky.
112 | See: http://www.python.org/doc/current/ref/types.html
113 | """
114 | mname = method_name(method)
115 | never_echo = "__str__", "__repr__", # Avoid recursion printing method calls
116 | if mname in never_echo:
117 | pass
118 | elif is_classmethod(method):
119 | setattr(klass, mname, classmethod(echo(method.__func__, write)))
120 | else:
121 | setattr(klass, mname, echo(method, write))
122 |
123 |
124 | def echo_class(klass, write=sys.stdout.write):
125 | """ Echo calls to class methods and static functions
126 | """
127 | for _, method in inspect.getmembers(klass, inspect.ismethod):
128 | echo_instancemethod(klass, method, write)
129 | for _, fn in inspect.getmembers(klass, inspect.isfunction):
130 | setattr(klass, name(fn), staticmethod(echo(fn, write)))
131 |
132 |
133 | def echo_module(mod, write=sys.stdout.write):
134 | """ Echo calls to functions and methods in a module.
135 | """
136 | for fname, fn in inspect.getmembers(mod, inspect.isfunction):
137 | setattr(mod, fname, echo(fn, write))
138 | for _, klass in inspect.getmembers(mod, inspect.isclass):
139 | echo_class(klass, write)
140 |
141 | if __name__ == "__main__":
142 | import doctest
143 |
144 | optionflags = doctest.ELLIPSIS
145 | doctest.testfile('echoexample.txt', optionflags=optionflags)
146 | doctest.testmod(optionflags=optionflags)
147 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/importlib2.py:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 |
3 | # Copyright (c) 2013 Peter M. Elias
4 |
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
6 | # of this software and associated documentation files (the "Software"), to deal
7 | # in the Software without restriction, including without limitation the rights
8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | # copies of the Software, and to permit persons to whom the Software is
10 | # furnished to do so, subject to the following conditions:
11 |
12 | # The above copyright notice and this permission notice shall be included in all
13 | # copies or substantial portions of the Software.
14 |
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | # SOFTWARE
22 |
23 |
24 | def import_module(target, relative_to=None):
25 | target_parts = target.split('.')
26 | target_depth = target_parts.count('')
27 | target_path = target_parts[target_depth:]
28 | target = target[target_depth:]
29 | fromlist = [target]
30 | if target_depth and relative_to:
31 | relative_parts = relative_to.split('.')
32 | relative_to = '.'.join(relative_parts[:-(target_depth - 1) or None])
33 | if len(target_path) > 1:
34 | relative_to = '.'.join(filter(None, [relative_to]) + target_path[:-1])
35 | fromlist = target_path[-1:]
36 | target = fromlist[0]
37 | elif not relative_to:
38 | fromlist = []
39 | mod = __import__(relative_to or target, globals(), locals(), fromlist)
40 | return getattr(mod, target, mod)
41 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/platform.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 |
20 | import sys
21 |
22 | PLATFORM_WINDOWS = 'windows'
23 | PLATFORM_LINUX = 'linux'
24 | PLATFORM_BSD = 'bsd'
25 | PLATFORM_DARWIN = 'darwin'
26 | PLATFORM_UNKNOWN = 'unknown'
27 |
28 |
29 | def get_platform_name():
30 | if sys.platform.startswith("win"):
31 | return PLATFORM_WINDOWS
32 | elif sys.platform.startswith('darwin'):
33 | return PLATFORM_DARWIN
34 | elif sys.platform.startswith('linux'):
35 | return PLATFORM_LINUX
36 | elif sys.platform.startswith('bsd'):
37 | return PLATFORM_BSD
38 | else:
39 | return PLATFORM_UNKNOWN
40 |
41 | __platform__ = get_platform_name()
42 |
43 |
44 | def is_linux():
45 | return __platform__ == PLATFORM_LINUX
46 |
47 |
48 | def is_bsd():
49 | return __platform__ == PLATFORM_BSD
50 |
51 |
52 | def is_darwin():
53 | return __platform__ == PLATFORM_DARWIN
54 |
55 |
56 | def is_windows():
57 | return __platform__ == PLATFORM_WINDOWS
58 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/unicode_paths.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright (c) 2013 Will Bond
5 | #
6 | # Permission is hereby granted, free of charge, to any person obtaining a copy
7 | # of this software and associated documentation files (the "Software"), to deal
8 | # in the Software without restriction, including without limitation the rights
9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | # copies of the Software, and to permit persons to whom the Software is
11 | # furnished to do so, subject to the following conditions:
12 | #
13 | # The above copyright notice and this permission notice shall be included in
14 | # all copies or substantial portions of the Software.
15 | #
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | # SOFTWARE.
23 |
24 |
25 | import sys
26 |
27 | from watchdog.utils import platform
28 |
29 | try:
30 | # Python 2
31 | str_cls = unicode
32 | bytes_cls = str
33 | except NameError:
34 | # Python 3
35 | str_cls = str
36 | bytes_cls = bytes
37 |
38 |
39 | fs_encoding = sys.getfilesystemencoding()
40 | # This is used by Linux when the locale seems to be improperly set. UTF-8 tends
41 | # to be the encoding used by all distros, so this is a good fallback.
42 | fs_fallback_encoding = 'utf-8'
43 |
44 |
45 | def encode(path):
46 | if isinstance(path, str_cls):
47 | try:
48 | path = path.encode(fs_encoding, 'strict')
49 | except UnicodeEncodeError:
50 | if not platform.is_linux():
51 | raise
52 | path = path.encode(fs_fallback_encoding, 'strict')
53 | return path
54 |
55 |
56 | def decode(path):
57 | if isinstance(path, bytes_cls):
58 | try:
59 | path = path.decode(fs_encoding, 'strict')
60 | except UnicodeDecodeError:
61 | if not platform.is_linux():
62 | raise
63 | path = path.decode(fs_fallback_encoding, 'strict')
64 | return path
65 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/utils/win32stat.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Copyright 2014 Thomas Amland
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """
18 | :module: watchdog.utils.win32stat
19 | :synopsis: Implementation of stat with st_ino and st_dev support.
20 |
21 | Functions
22 | ---------
23 |
24 | .. autofunction:: stat
25 |
26 | """
27 |
28 | import ctypes
29 | import ctypes.wintypes
30 | import stat as stdstat
31 | from collections import namedtuple
32 |
33 |
34 | INVALID_HANDLE_VALUE = ctypes.c_void_p(-1).value
35 | OPEN_EXISTING = 3
36 | FILE_READ_ATTRIBUTES = 0x80
37 | FILE_ATTRIBUTE_NORMAL = 0x80
38 | FILE_ATTRIBUTE_READONLY = 0x1
39 | FILE_ATTRIBUTE_DIRECTORY = 0x10
40 | FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
41 | FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
42 |
43 |
44 | class FILETIME(ctypes.Structure):
45 | _fields_ = [("dwLowDateTime", ctypes.wintypes.DWORD),
46 | ("dwHighDateTime", ctypes.wintypes.DWORD)]
47 |
48 |
49 | class BY_HANDLE_FILE_INFORMATION(ctypes.Structure):
50 | _fields_ = [('dwFileAttributes', ctypes.wintypes.DWORD),
51 | ('ftCreationTime', FILETIME),
52 | ('ftLastAccessTime', FILETIME),
53 | ('ftLastWriteTime', FILETIME),
54 | ('dwVolumeSerialNumber', ctypes.wintypes.DWORD),
55 | ('nFileSizeHigh', ctypes.wintypes.DWORD),
56 | ('nFileSizeLow', ctypes.wintypes.DWORD),
57 | ('nNumberOfLinks', ctypes.wintypes.DWORD),
58 | ('nFileIndexHigh', ctypes.wintypes.DWORD),
59 | ('nFileIndexLow', ctypes.wintypes.DWORD)]
60 |
61 |
62 | CreateFile = ctypes.windll.kernel32.CreateFileW
63 | CreateFile.restype = ctypes.wintypes.HANDLE
64 | CreateFile.argtypes = (
65 | ctypes.c_wchar_p,
66 | ctypes.wintypes.DWORD,
67 | ctypes.wintypes.DWORD,
68 | ctypes.c_void_p,
69 | ctypes.wintypes.DWORD,
70 | ctypes.wintypes.DWORD,
71 | ctypes.wintypes.HANDLE,
72 | )
73 |
74 | GetFileInformationByHandle = ctypes.windll.kernel32.GetFileInformationByHandle
75 | GetFileInformationByHandle.restype = ctypes.wintypes.BOOL
76 | GetFileInformationByHandle.argtypes = (
77 | ctypes.wintypes.HANDLE,
78 | ctypes.wintypes.POINTER(BY_HANDLE_FILE_INFORMATION),
79 | )
80 |
81 | CloseHandle = ctypes.windll.kernel32.CloseHandle
82 | CloseHandle.restype = ctypes.wintypes.BOOL
83 | CloseHandle.argtypes = (ctypes.wintypes.HANDLE,)
84 |
85 |
86 | StatResult = namedtuple('StatResult', 'st_dev st_ino st_mode st_mtime')
87 |
88 | def _to_mode(attr):
89 | m = 0
90 | if (attr & FILE_ATTRIBUTE_DIRECTORY):
91 | m |= stdstat.S_IFDIR | 0o111
92 | else:
93 | m |= stdstat.S_IFREG
94 | if (attr & FILE_ATTRIBUTE_READONLY):
95 | m |= 0o444
96 | else:
97 | m |= 0o666
98 | return m
99 |
100 | def _to_unix_time(ft):
101 | t = (ft.dwHighDateTime) << 32 | ft.dwLowDateTime
102 | return (t / 10000000) - 11644473600
103 |
104 | def stat(path):
105 | hfile = CreateFile(path,
106 | FILE_READ_ATTRIBUTES,
107 | 0,
108 | None,
109 | OPEN_EXISTING,
110 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
111 | None)
112 | if hfile == INVALID_HANDLE_VALUE:
113 | raise ctypes.WinError()
114 | info = BY_HANDLE_FILE_INFORMATION()
115 | r = GetFileInformationByHandle(hfile, info)
116 | CloseHandle(hfile)
117 | if not r:
118 | raise ctypes.WinError()
119 | return StatResult(st_dev=info.dwVolumeSerialNumber,
120 | st_ino=(info.nFileIndexHigh << 32) + info.nFileIndexLow,
121 | st_mode=_to_mode(info.dwFileAttributes),
122 | st_mtime=_to_unix_time(info.ftLastWriteTime)
123 | )
124 |
--------------------------------------------------------------------------------
/Packages/SourcePawn/watchdog/version.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # Copyright 2011 Yesudeep Mangalapilly
5 | # Copyright 2012 Google, Inc.
6 | #
7 | # Licensed under the Apache License, Version 2.0 (the "License");
8 | # you may not use this file except in compliance with the License.
9 | # You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 |
19 |
20 | # When updating this version number, please update the
21 | # ``docs/source/global.rst.inc`` file as well.
22 | VERSION_MAJOR = 0
23 | VERSION_MINOR = 8
24 | VERSION_BUILD = 0
25 | VERSION_INFO = (VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD)
26 | VERSION_STRING = "%d.%d.%d" % VERSION_INFO
27 |
28 | __version__ = VERSION_INFO
29 |
--------------------------------------------------------------------------------
/Packages/User/Preferences.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | "color_scheme": "Packages/User/SaucePawn.sublime-color-scheme",
3 | "font_face": "",
4 | "font_size": 9,
5 | "theme": "Adaptive.sublime-theme"
6 | }
7 |
--------------------------------------------------------------------------------
/Packages/User/SaucePawn.sublime-color-scheme:
--------------------------------------------------------------------------------
1 | {
2 | "name": "JS SourcePawn Theme",
3 | "globals":
4 | {
5 | "background": "#2c3e50",
6 | "foreground": "#f2e5d8",
7 | "caret": "#F8F8F0",
8 | "brackets_options": "foreground bold",
9 | "brackets_foreground": "#9deafa",
10 | "invisibles": "#49483E",
11 | "line_highlight": "#49483E",
12 | "selection": "#49483E",
13 | // "gutter": "#000000",
14 | // "gutter_foreground": "#ffffff",
15 | },
16 | "rules":
17 | [
18 | {
19 | "scope": "brackethighlighter.default",
20 | "background": "#d1d1d1",
21 | "foreground": "#f4f5f7"
22 | },
23 | {
24 | "scope": "comment",
25 | "foreground": "#5b727f"
26 | },
27 | // Constant
28 | {
29 | "scope": "constant",
30 | "foreground": "#74b8f9",
31 | },
32 | {
33 | "scope": "constant.character, constant.other",
34 | "foreground": "#97cefc",
35 | },
36 | {
37 | "scope": "constant.character.escape",
38 | "foreground": "#76a9d3",
39 | },
40 | {
41 | "scope": "constant.language",
42 | "foreground": "#7fc0fa",
43 | "font_style": "italic bold",
44 | },
45 | {
46 | "scope": "constant.numeric",
47 | "foreground": "#74b8f9",
48 | "font_style": "italic",
49 | },
50 | // Entity
51 | {
52 | "scope": "entity.name.class",
53 | "foreground": "#31e0f7",
54 | "font_style": "bold italic underline"
55 | },
56 | {
57 | "scope": "entity.name.constant",
58 | "foreground": "#dd96e0",
59 | "font_style": "bold italic"
60 | },
61 | {
62 | "scope": "entity.name.enum",
63 | "foreground": "#31e0f7",
64 | "font_style": "bold italic",
65 | },
66 | {
67 | "scope": "entity.name.function",
68 | "foreground": "#a7abfc", // c2c5f9
69 | "font_style": "bold italic"
70 | },
71 | {
72 | "scope": "entity.name.struct",
73 | "foreground": "#31e0f7",
74 | "font_style": "bold italic underline",
75 | },
76 | {
77 | "scope": "entity.name.tag",
78 | "foreground": "#ff785f"
79 | },
80 | {
81 | "scope": "entity.name.trait",
82 | "foreground": "#A7F0A9",
83 | "font_style": "bold italic"
84 | },
85 | {
86 | "scope": "entity.name.type",
87 | "foreground": "#31e0f7",
88 | "font_style": "bold italic",
89 | },
90 | {
91 | "scope": "entity.other.attribute-name",
92 | "foreground": "#89e99c",
93 | },
94 | {
95 | "scope" : "entity.other.inherited-class",
96 | "foreground": "#31e0f7",
97 | "font_style": "bold italic"
98 | },
99 | // Invalid
100 | {
101 | "scope": "invalid",
102 | "foreground": "#F8F8F0",
103 | "background": "#F92672"
104 | },
105 | {
106 | "scope": "invalid.deprecated",
107 | "background": "#AE81FF",
108 | "foreground": "#F8F8F0",
109 | },
110 | {
111 | "scope": "invalid.illegal",
112 | "foreground": "#F8F8F0",
113 | "background": "#F92672",
114 | },
115 | // KeyWord
116 | {
117 | "scope": "keyword",
118 | "foreground": "#ff624a",
119 | },
120 | {
121 | "scope": "keyword.control",
122 | "foreground": "#ef7c66",
123 | // "font_style": "bold",
124 | },
125 | {
126 | "scope": "keyword.control.flow",
127 | "foreground": "#ef7c66",
128 | "font_style": "italic",
129 | },
130 | {
131 | "scope": "keyword.control.conditional",
132 | "foreground": "#ef7c66",
133 | "font_style": ""
134 | },
135 | {
136 | "scope": "keyword.control.import",
137 | "foreground": "#ff624a",
138 | "font_style": "italic",
139 | },
140 | {
141 | "scope": "keyword.declaration",
142 | "foreground": "#54afff",
143 | "font_style": "italic"
144 | },
145 | {
146 | "scope": "keyword.operator",
147 | "foreground": "#ff624a",
148 | },
149 | {
150 | "scope": "keyword.operator.bitwise",
151 | "foreground": "#e80202",
152 | },
153 | {
154 | "scope": "keyword.operator.logical",
155 | "foreground": "#e80202",
156 | },
157 | {
158 | "scope": "keyword.operator.word",
159 | "foreground":"#ef7c66"
160 | },
161 | {
162 | "scope": "keyword.other",
163 | "foreground": "#54afff",
164 | "font_style": "bold",
165 | },
166 | {
167 | "scope": "keyword.other.documentation",
168 | "foreground": "#de8071",
169 | "font_style": ""
170 | },
171 | {
172 | "scope": "keyword.other.documentation.note",
173 | "foreground": "#de2323",
174 | // "font_style": "bold",
175 | },
176 | // Meta
177 | {
178 | "scope": "meta",
179 | "foreground": "#ffffff",
180 | },
181 | {
182 | "scope": "meta.preprocessor",
183 | "foreground": "#de8071",
184 | },
185 | // Punctuation
186 | {
187 | "scope": "punctuation.accessor",
188 | "foreground": "#e80202",
189 | },
190 | {
191 | "scope": "punctuation.definition",
192 | "foreground": "#b5837b",
193 | },
194 | {
195 | "scope": "punctuation.definition.comment",
196 | "foreground": "#5b727f",
197 | },
198 | {
199 | "scope": "punctuation.definition.generic",
200 | "foreground": "#ff624a",
201 | },
202 | {
203 | "scope": "punctuation.definition.keyword",
204 | "foreground": "#a66c63",
205 | },
206 | {
207 | "scope": "punctuation.definition.string",
208 | "foreground": "#f57a7a",
209 | },
210 | {
211 | "scope": "punctuation.section.block",
212 | "foreground": "#ccdfff",
213 | "font_style": "bold",
214 | },
215 | {
216 | "scope": "punctuation.section",
217 | "foreground": "#96b1d3",
218 | "font_style": "bold",
219 | },
220 | {
221 | "scope": "punctuation.section.braces",
222 | "foreground": "#ccdfff",
223 | // "font_style": "bold",
224 | },
225 | {
226 | "scope": "punctuation.section.brackets",
227 | "foreground": "#6f8fb7",
228 | },
229 | {
230 | "scope": "punctuation.section.parens",
231 | "foreground": "#96b1d3",
232 | "font_style": "bold",
233 | },
234 | {
235 | "scope": "punctuation.separator",
236 | "foreground": "#9fcbf2",
237 | },
238 | {
239 | "scope": "punctuation.terminator",
240 | "foreground": "#21bfff",
241 | },
242 | {
243 | "scope": "source",
244 | "foreground": "#ffffff"
245 | },
246 | // Storage
247 | {
248 | "scope": "storage",
249 | "foreground": "#54afff",
250 | },
251 | {
252 | "scope": "storage.modifier",
253 | "foreground": "#54afff",
254 | "font_style": "bold"
255 |
256 | },
257 | {
258 | "scope": "storage.type",
259 | "foreground": "#66D9EF",
260 | // "font_style": "bold",
261 | },
262 | {
263 | "scope": "string",
264 | "foreground": "#ffaaaa",
265 | "font_style":"italic"
266 | },
267 | // Support
268 | {
269 | "scope": "support",
270 | "foreground": "#bbdaf2"
271 | },
272 | {
273 | "scope": "support.constant",
274 | "foreground": "#dd96e0",
275 | "font_style": "bold italic"
276 | },
277 | {
278 | "scope": "support.class",
279 | "foreground": "#31e0f7",
280 | "font_style": "bold italic"
281 | },
282 | {
283 | "scope": "support.function",
284 | "foreground": "#a7abfc",
285 | "font_style": "bold"
286 | },
287 | {
288 | "scope": "support.other.variable",
289 | "foreground": "#ffffff",
290 | "font_style": "bold"
291 | },
292 | {
293 | "scope": "support.type",
294 | "foreground": "#66D9EF",
295 | "font_style": "italic"
296 | },
297 | // Variable
298 | {
299 | "scope": "variable",
300 | "foreground": "#ffffff",
301 | },
302 | {
303 | "scope": "variable.function",
304 | "foreground": "#8ed1b9",
305 | // "font_style": "bold"
306 | // "font_style": "italic"
307 | },
308 | {
309 | "scope": "variable.language",
310 | "foreground": "#1fc6ab",
311 | "font_style":"italic"
312 | },
313 | {
314 | "scope": "variable.other",
315 | "foreground": "#bbdaf2",
316 | // "font_style":"italic"
317 | },
318 | {
319 | "scope": "variable.other.constant",
320 | "foreground": "#dd96e0",
321 | "font_style":"italic"
322 | },
323 | {
324 | "scope": "variable.other.member",
325 | "foreground": "#ffaf4f",
326 | // "font_style":"italic bold"
327 | },
328 | {
329 | "scope": "variable.other.readwrite",
330 | "foreground": "#ffffff",
331 | // "font_style":"italic"
332 | },
333 | {
334 | "scope": "variable.parameter",
335 | "foreground": "#ffd687",
336 | // "font_style": "italic"
337 | },
338 | ]
339 | }
--------------------------------------------------------------------------------
/Packages/User/SourcePawn Completions.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | "bootstrapped": true,
3 | // path to sourcemod "scripting/include" folder
4 | // Windows example: // Support for multiple directories. Searches top to bottom until it finds include
5 | // "include_directory": [
6 | // "D:\\sourcemod\\scripting\\include",
7 | // "C:\\another\\sourcemod\\include", // optional
8 | /// "etc . . ." // optional
9 | // ],
10 | // OSX example:
11 | // "include_directory": [
12 | // "/Users/ppalex/sourcemod/scripting/include",
13 | // "/Users/ppalex/some/other/sourcemod/scripting/include", // optional
14 | // "etc . . ." // optional
15 | // ],
16 |
17 | // delay (in seconds) before regenerating auto-completion snippets
18 | "live_refresh_delay": 1.0
19 | }
20 |
--------------------------------------------------------------------------------
/Packages/User/bh_core.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | "content_highlight_bar": true,
3 | "align_content_highlight_bar": true,
4 | "search_threshold": 10000,
5 | // Define region highlight styles
6 | "bracket_styles": {
7 | // "default" and "unmatched" styles are special
8 | // styles. If they are not defined here,
9 | // they will be generated internally with
10 | // internal defaults.
11 |
12 | // "default" style defines attributes that
13 | // will be used for any style that does not
14 | // explicitly define that attribute. So if
15 | // a style does not define a color, it will
16 | // use the color from the "default" style.
17 | "default": {
18 | "icon": "dot",
19 | // BH1's original default color for reference
20 | // "color": "entity.name.class",
21 | "color": "brackethighlighter.default",
22 | "style": "outline"
23 | },
24 |
25 | // This particular style is used to highlight
26 | // unmatched bracekt pairs. It is a special
27 | // style.
28 | "unmatched": {
29 | "icon": "question",
30 | // "color": "brackethighlighter.unmatched",
31 | "style": "outline"
32 | },
33 | // User defined region styles
34 | "curly": {
35 | "icon": "curly_bracket",
36 | // "color": "brackethighlighter.curly",
37 | "style": "outline"
38 | },
39 | "round": {
40 | "icon": "round_bracket",
41 | // "color": "brackethighlighter.round",
42 | "style": "outline"
43 | },
44 | "square": {
45 | "icon": "square_bracket",
46 | // "color": "brackethighlighter.square",
47 | "style": "outline"
48 | },
49 | "angle": {
50 | "icon": "angle_bracket",
51 | // "color": "brackethighlighter.angle",
52 | "style": "outline"
53 | },
54 | "tag": {
55 | "icon": "tag",
56 | // "color": "brackethighlighter.tag",
57 | "style": "outline"
58 | },
59 | "single_quote": {
60 | "icon": "single_quote",
61 | // "color": "brackethighlighter.quote",
62 | "style": "outline"
63 | },
64 | "double_quote": {
65 | "icon": "double_quote",
66 | // "color": "brackethighlighter.quote",
67 | "style": "outline"
68 | },
69 | "regex": {
70 | "icon": "regex",
71 | // "color": "brackethighlighter.quote",
72 | "style": "outline"
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # sourcepawn_sublime_stuff
2 | Theme, syntax highlighter, bracket highlighter, whatever
3 |
4 | Requires Sublime Text 4 (Dev)
5 |
6 | This stuff goes in %APPDATA%\Sublime Folder Name Here/
7 |
8 | See https://github.com/JoinedSenses/sourcepawn_sublime_stuff/tree/master/Packages/SourcePawn for configuring
9 |
10 |
11 |
--------------------------------------------------------------------------------