├── .gitignore ├── Commands ├── Coding Style Fixer.tmCommand ├── Completion.tmCommand ├── Documentation for Tag.tmCommand ├── Function Tooltip.tmCommand ├── Help.tmCommand ├── Insert Call to Parent.tmCommand ├── Jump to Included File.tmCommand ├── Lookup word in PHP manual.plist ├── PHPDoc Help.tmCommand ├── Post-doc.tmCommand ├── Run PHP.plist ├── Special: Return Inside an Empty Tag.tmCommand ├── Validate syntax.plist └── Wrap Docblock at 80 Characters.tmCommand ├── DragCommands └── Include dropped file.tmDragCommand ├── Preferences ├── Add Magic Methods to the Symbol List.tmPreferences ├── Add goto labels to symbol list.tmPreferences ├── Comments.plist ├── Completion: includes.tmPreferences ├── Completions.tmPreferences ├── Disable spellcheck in require.tmPreferences ├── Enable Spellchecking for Docblocks.tmPreferences ├── Folding.tmPreferences ├── Indentation Arrays.tmPreferences ├── Indentation Rules.tmPreferences ├── Miscellaneous.plist └── Symbols List: functions.tmPreferences ├── README.mdown ├── Snippets ├── $GLOBALS[''].tmSnippet ├── $_COOKIE[''].tmSnippet ├── $_ENV[''].tmSnippet ├── $_FILES[''].tmSnippet ├── $_GET[''].tmSnippet ├── $_POST[''].tmSnippet ├── $_REQUEST[''].tmSnippet ├── $_SERVER[''].tmSnippet ├── $_SESSION[''].tmSnippet ├── … ?>.tmSnippet ├── .tmSnippet ├── … ?>.tmSnippet ├── .tmSnippet ├── .tmSnippet ├── .tmSnippet ├── .tmSnippet ├── ___ ___ .tmSnippet ├── ___ .tmSnippet ├── ?>… 2 | 3 | 4 | 5 | beforeRunningCommand 6 | saveActiveFile 7 | command 8 | #!/bin/bash 9 | ${TM_PHP_CS_FIXER:-php-cs-fixer} fix -n $TM_PHP_CS_FIXER_OPTIONS "$TM_FILEPATH"|fold -s 10 | 11 | input 12 | none 13 | inputFormat 14 | text 15 | keyEquivalent 16 | ^H 17 | name 18 | Coding Style Fixer 19 | outputCaret 20 | afterOutput 21 | outputFormat 22 | html 23 | outputLocation 24 | toolTip 25 | requiredCommands 26 | 27 | 28 | command 29 | php-cs-fixer 30 | locations 31 | 32 | /usr/local/bin/php-cs-fixer 33 | 34 | variable 35 | TM_PHP_CS_FIXER 36 | 37 | 38 | scope 39 | text.html.php 40 | uuid 41 | F82CE7A9-5E20-4B01-95EE-85255FB5A489 42 | version 43 | 2 44 | 45 | 46 | -------------------------------------------------------------------------------- /Commands/Completion.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby18 -wKU 9 | require ENV['TM_SUPPORT_PATH'] + '/lib/osx/plist' 10 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui' 11 | 12 | choices = OSX::PropertyList.load(File.read(ENV['TM_BUNDLE_SUPPORT'] + '/functions.plist')) 13 | TextMate::UI.complete(choices, :initial_filter => ENV['TM_CURRENT_WORD'], :extra_chars => '_') 14 | 15 | fallbackInput 16 | word 17 | input 18 | selection 19 | keyEquivalent 20 | ~ 21 | name 22 | Completions for Word… 23 | output 24 | showAsTooltip 25 | scope 26 | source.php 27 | uuid 28 | 7E7936B6-7334-455B-A5ED-D51CA49CF532 29 | 30 | 31 | -------------------------------------------------------------------------------- /Commands/Documentation for Tag.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env bash 9 | [[ -f "${TM_SUPPORT_PATH}/lib/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh" 10 | 11 | if grep <<<${TM_CURRENT_WORD:-!} -Esq '[@a-zA-Z]+' 12 | then exit_show_html "<meta http-equiv='Refresh' content='0;URL=http://manual.phpdoc.org/HTMLframesConverter/earthli/phpDocumentor/tutorial_tags.${TM_CURRENT_WORD#@}.pkg.html'>" 13 | else echo "Nothing to lookup (hint: place the caret on a tag)" 14 | fi 15 | input 16 | none 17 | inputFormat 18 | text 19 | keyEquivalent 20 | ^h 21 | name 22 | Documentation for Tag 23 | outputCaret 24 | afterOutput 25 | outputFormat 26 | text 27 | outputLocation 28 | toolTip 29 | scope 30 | comment.block.documentation.phpdoc.php 31 | semanticClass 32 | lookup.define.php 33 | uuid 34 | 42F50AE3-4F1C-43EB-9722-D80261A19625 35 | version 36 | 2 37 | 38 | 39 | -------------------------------------------------------------------------------- /Commands/Function Tooltip.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby18 -wKU 9 | 10 | SUPPORT = ENV['TM_SUPPORT_PATH'] 11 | DIALOG = SUPPORT + '/bin/tm_dialog' 12 | 13 | require SUPPORT + '/lib/escape' 14 | require SUPPORT + '/lib/osx/plist' 15 | 16 | require ENV['TM_BUNDLE_SUPPORT'] + '/lib/php.rb' 17 | require ENV['TM_SUPPORT_PATH'] + '/lib/ui' 18 | require ENV['TM_SUPPORT_PATH'] + '/lib/exit_codes' 19 | 20 | # ENV['TM_BUNDLE_SUPPORT'] = '/Library/Application Support/TextMate/Bundles/PHP.tmbundle/Support/' 21 | # ENV['TM_CURRENT_LINE'] = 'dummy(array_merge(array("array", "number", "one"), array("array2")))' 22 | # ENV['TM_LINE_INDEX'] = '53' 23 | # 24 | # ENV['TM_CURRENT_LINE'] = "date('Y-m-d', time() + ONE_MONTH)" 25 | # ENV['TM_LINE_INDEX'] = '23' 26 | 27 | lang = ENV['LANG'] ? ENV['LANG'][0..2] : 'en' 28 | $fnFilename = ENV['TM_BUNDLE_SUPPORT'] + '/function-docs/' + lang + '.txt' 29 | 30 | if !File.exist?($fnFilename) 31 | $fnFilename = ENV['TM_BUNDLE_SUPPORT'] + '/function-docs/en.txt' 32 | end 33 | 34 | class String 35 | def nbsp 36 | gsub(' ', '&nbsp;') 37 | end 38 | end 39 | 40 | def show_function_and_exit(function, line = nil) 41 | return unless function =~ /^[A-Za-z_][A-Za-z0-9_]*$/ 42 | functions = `grep -i '^#{function}%' "#{$fnFilename}"`.split("\n") 43 | 44 | if functions.size == 1 45 | function, prototype, description = functions.pop.split('%') 46 | 47 | function = PHPFunction.new(prototype) 48 | 49 | params = function.params.map do |param| 50 | html = '' 51 | html << '<span class="type">' + param[:type] + '</span> '.nbsp unless param[:type].to_s.empty? 52 | html << param[:name] 53 | unless param[:default].to_s.empty? 54 | html << ' = '.nbsp + param[:default] 55 | end 56 | html = '<i>[' + html + ']</i>' if param[:optional] 57 | html 58 | end 59 | 60 | if line 61 | arg = 0 62 | depth = 0 63 | line.reverse.each_byte do |char| 64 | if char == ?, and depth == 0 65 | arg += 1 66 | elsif char == ?( 67 | depth -= 1 if depth > 0 68 | elsif char == ?) 69 | depth += 1 70 | end 71 | end 72 | if arg < params.size 73 | params[arg] = '<b>' + params[arg] + '</b>' 74 | elsif not params.empty? 75 | params[-1] = '<b>' + params[-1] + '</b>' 76 | end 77 | end 78 | prototype = '<span class="type">' + function.type + '</span> <span>'.nbsp + function.name + '</span>(' + params.join(', '.nbsp) + ')' 79 | tip = <<-HTML 80 | <style type="text/css" media="screen"> 81 | p { 82 | margin: 0; 83 | } 84 | p.prototype span { 85 | color: #00008B; 86 | } 87 | p.prototype i { 88 | color: #666; 89 | } 90 | p.description { 91 | font-size: smaller; 92 | } 93 | p.prototype span.type { 94 | color: #006400; 95 | } 96 | </style> 97 | <p class="prototype">#{prototype}</p> 98 | <p class="description">#{description}</p> 99 | HTML 100 | TextMate::UI.tool_tip tip, :format => :html 101 | exit 102 | end 103 | end 104 | 105 | function = nil 106 | 107 | show_function_and_exit(function = ENV['TM_CURRENT_WORD'].to_s) 108 | 109 | prefix = ENV['TM_CURRENT_LINE'][0..ENV['TM_LINE_INDEX'].to_i].reverse 110 | 111 | # Keep moving back a function call until we get a match and exit 112 | while prefix =~ /\(\s*(\w+)/ 113 | show_function_and_exit(function = $1.reverse, ENV['TM_CURRENT_LINE'][($' + $&).length..ENV['TM_LINE_INDEX'].to_i - 1]) 114 | prefix = prefix[$&.length..-1] 115 | end 116 | 117 | show_function_and_exit(function = $1) if ENV['TM_CURRENT_LINE'][0..ENV['TM_LINE_INDEX'].to_i] =~ /(\w+)\($/ 118 | 119 | TextMate.exit_show_tool_tip "Function not found: " + function.to_s 120 | 121 | fallbackInput 122 | line 123 | input 124 | none 125 | inputFormat 126 | xml 127 | keyEquivalent 128 | ~ 129 | name 130 | Documentation for Function Call (tool tip) 131 | output 132 | showAsTooltip 133 | scope 134 | source.php 135 | uuid 136 | 19A164B7-4A3C-421B-9866-85FB9077A983 137 | 138 | 139 | -------------------------------------------------------------------------------- /Commands/Help.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/bin/bash 9 | [[ -f "${TM_SUPPORT_PATH}/lib/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh" 10 | 11 | . "$TM_SUPPORT_PATH/lib/webpreview.sh" 12 | html_header "PHP Bundle Help" "PHP" 13 | "$TM_SUPPORT_PATH/lib/markdown_to_help.rb" "$TM_BUNDLE_SUPPORT/help.markdown" 14 | html_footer 15 | 16 | input 17 | none 18 | inputFormat 19 | text 20 | name 21 | Help 22 | outputCaret 23 | afterOutput 24 | outputFormat 25 | html 26 | outputLocation 27 | newWindow 28 | scope 29 | text.html.php 30 | uuid 31 | C81F7FF7-7899-48F5-AD79-F248B7BC3DCB 32 | version 33 | 2 34 | 35 | 36 | -------------------------------------------------------------------------------- /Commands/Insert Call to Parent.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env php 9 | <?php 10 | 11 | $functionToken = false; 12 | $functionName = false; 13 | 14 | if (getenv('TM_CURRENT_WORD') == '') { 15 | // try only, if current word is empty (will be '$' if trigger occured for '$parent') 16 | $seekLine = intval(getenv('TM_LINE_NUMBER')); 17 | $tokens = token_get_all(file_get_contents('php://stdin')); 18 | $numTokens = count($tokens); 19 | 20 | $startToken = false; 21 | 22 | // Find the first token that's on/after TM_LINE_NUMBER 23 | for ($x = 0; $x < $numTokens; $x++) { 24 | if (is_array($tokens[$x]) && $tokens[$x][2] >= $seekLine) { 25 | $startToken = $x; 26 | break; 27 | } 28 | } 29 | 30 | // Could not find the line, so just start from the end 31 | if (false === $startToken) { 32 | $startToken = $numTokens - 1; 33 | } 34 | 35 | // Work backwards until we find the function declaration 36 | for ($x = $startToken; $x >= 0; $x--) { 37 | if (is_array($tokens[$x]) && T_FUNCTION === $tokens[$x][0]) { 38 | // Try to find a function name, which may not exist if this is a closure 39 | for ($y = $x + 1; $y < $numTokens; $y++) { 40 | if (is_array($tokens[$y])) { 41 | if (T_STRING === $tokens[$y][0]) { 42 | $functionToken = $y; 43 | $functionName = $tokens[$y][1]; 44 | break 2; 45 | } 46 | } else if ($tokens[$y] === '(') { 47 | break; 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | // No function declaration found, so let's act like we were never here 55 | if (false === $functionToken || false === $functionName) { 56 | echo 'parent'; 57 | 58 | if ('YES' === getenv('TM_SOFT_TABS')) { 59 | // Only use enough spaces to get to the next "tab stop" 60 | $tabSize = getenv('TM_TAB_SIZE'); 61 | $col = intval(getenv('TM_COLUMN_NUMBER')) + 5; 62 | echo str_repeat(' ', $tabSize - ($col % $tabSize)); 63 | } else { 64 | echo "\t"; 65 | } 66 | 67 | exit(); 68 | } 69 | 70 | $firstParenFound = false; 71 | $skipParens = 0; 72 | $numParams = 0; 73 | $params = array(); 74 | 75 | for ($x = $functionToken + 1; $x < $numTokens; $x++) { 76 | $token = $tokens[$x]; 77 | 78 | if ($firstParenFound && is_array($token)) { 79 | if (T_VARIABLE === $token[0]) { 80 | $numParams++; 81 | $params[] = "\${{$numParams}:" . str_replace('$', '\$', $token[1]) . '}'; 82 | } 83 | } else { 84 | switch ($token) { 85 | case '(': 86 | if ($firstParenFound) { 87 | $skipParens++; 88 | } else { 89 | $firstParenFound = true; 90 | } 91 | break; 92 | case ')': 93 | if ($skipParens) { 94 | $skipParens--; 95 | } else if ($firstParenFound) { 96 | break 2; 97 | } 98 | break; 99 | default: 100 | break; 101 | } 102 | } 103 | } 104 | 105 | echo "parent::{$functionName}(" . implode(', ', $params) . ');$0'; 106 | input 107 | document 108 | name 109 | Insert Call to Parent 110 | output 111 | insertAsSnippet 112 | scope 113 | source.php 114 | tabTrigger 115 | parent 116 | uuid 117 | 978B5E5E-F5C6-4FD8-B346-B0C85883D600 118 | 119 | 120 | -------------------------------------------------------------------------------- /Commands/Jump to Included File.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/bin/bash 9 | 10 | # This command passes the script to Ruby via a heredoc, rather than using a shebang. 11 | # The reason for this is so that .textmate_init is sourced, which IMO is the nicest place to set PHP_INCLUDE_PAT 12 | # However passing the heredoc axes the document STDIN from TextMate, so here we redirect the original STDIN to 13 | # file descriptor 3, to be later read from the Ruby script 14 | ruby18 3>&0 <<-'RUBY' 15 | require ENV["TM_SUPPORT_PATH"] + "/lib/ui.rb" 16 | require ENV["TM_SUPPORT_PATH"] + "/lib/textmate.rb" 17 | 18 | options = [] 19 | 20 | if ENV['TM_CURRENT_LINE'] =~ /(?:include|require)(?:_once)?\s*\(?\s*?['"](.+)['"]\s*\)?/ 21 | options << $1 22 | else 23 | IO.open(3, 'r') do |document| # This reads the TextMate document from file descriptor 3, as describe above 24 | document.read.scan(/(?:include|require)(?:_once)?\s*\(?\s*?['"](.+)['"]\s*\)?/).each do |path| 25 | options << path[0] unless path[0].include?('$') # Skip dynamic includes 26 | end 27 | end 28 | end 29 | 30 | abort "No includes found" if options.empty? 31 | 32 | file = '' 33 | if options.size > 1 34 | abort unless choice = TextMate::UI.menu(options) 35 | file = options[choice] 36 | else 37 | file = options.pop 38 | end 39 | 40 | paths = [] 41 | if ENV['PHP_INCLUDE_PATH'] 42 | paths = ENV['PHP_INCLUDE_PATH'].split(':') 43 | else 44 | paths = [ENV['TM_DIRECTORY']] 45 | end 46 | 47 | paths.each do |path| 48 | expanded_path = File.expand_path(file, path) 49 | if File.exists?(expanded_path) 50 | TextMate.go_to :file => expanded_path 51 | exit 52 | end 53 | end 54 | puts "File not found: #{file}" 55 | puts "Set PHP_INCLUDE_PATH for best results" unless ENV['PHP_INCLUDE_PATH'] 56 | RUBY 57 | 58 | input 59 | document 60 | inputFormat 61 | text 62 | keyEquivalent 63 | @D 64 | name 65 | Jump to Included File 66 | outputCaret 67 | afterOutput 68 | outputFormat 69 | text 70 | outputLocation 71 | toolTip 72 | scope 73 | source.php 74 | uuid 75 | B3E79B47-40E9-4EF9-BAD9-11FEEE0D238F 76 | version 77 | 2 78 | 79 | 80 | -------------------------------------------------------------------------------- /Commands/Lookup word in PHP manual.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | bundlePath 8 | /Users/kumar/Library/Application Support/TextMate/Bundles/Custom.tmbundle 9 | command 10 | #!/usr/bin/env bash 11 | [[ -f "${TM_SUPPORT_PATH}/lib/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh" 12 | 13 | if grep <<<${TM_CURRENT_WORD:-!} -Esq '^[a-zA-Z0-9_]+$' 14 | then 15 | if URL=`grep -i "^$TM_CURRENT_WORD=" "$TM_BUNDLE_SUPPORT/documentation.txt"` 16 | then 17 | URL=${URL:${#TM_CURRENT_WORD}+1} 18 | else 19 | URL="function.${TM_CURRENT_WORD//_/-}" 20 | fi 21 | if [[ "$PHP_MANUAL_LOCATION" ]] 22 | then 23 | if [[ ! -d "$PHP_MANUAL_LOCATION" ]] 24 | then 25 | exit_show_tool_tip "Your PHP_MANUAL_LOCATION directory ($PHP_MANUAL_LOCATION) does not exist. See the bundle Help for setup instructions." 26 | fi 27 | if [[ ! -f "$PHP_MANUAL_LOCATION/$URL.html" ]] 28 | then 29 | exit_show_tool_tip "No documentation found for '$TM_CURRENT_WORD'" 30 | fi 31 | . "$TM_SUPPORT_PATH/lib/webpreview.sh" 32 | html_header "PHP Help" "${TM_FILENAME:-}" 33 | cat <<-'HTML' 34 | <script type="text/javascript" charset="utf-8"> 35 | function jump(page) { 36 | TextMate.isBusy = true; 37 | res = TextMate.system('cat "$PHP_MANUAL_LOCATION"/' + page, null).outputString; 38 | document.getElementById('php_help').innerHTML = res; 39 | TextMate.isBusy = false; 40 | setupLinks(); 41 | 42 | historyList = document.getElementById('history_list'); 43 | TextMate.log(historyList); 44 | item = document.createElement('option'); 45 | TextMate.log(item); 46 | item.value = page; 47 | TextMate.log(page); 48 | item.innerText = res.match(/>(.+?)<\/TITLE/i)[1]; 49 | historyList.appendChild(item); 50 | item.selected = true; 51 | } 52 | 53 | function setupLinks() { 54 | var link, links = document.links; 55 | for (i = 0; i < links.length; i++) { 56 | link = links[i]; 57 | if (matches = link.href.match(/^x-txmt-command:.+\/(.+.html)$/)) { 58 | link.href = 'javascript:jump("' + matches[1] + '")'; 59 | } 60 | } 61 | } 62 | </script> 63 | HTML 64 | echo '<select id="history_list" onchange="jump(this.options[this.selectedIndex].value)"></select>' 65 | echo '<div id="php_help"></div>' 66 | echo '<script>jump("'"$URL"'.html");</script>' 67 | html_footer 68 | exit_show_html 69 | else URL="http://php.net/manual/en/$URL.php" 70 | fi 71 | exit_show_html "<meta http-equiv='Refresh' content='0;URL=$URL'>" 72 | else echo "Nothing to lookup (hint: place the caret on a function name)" 73 | fi 74 | input 75 | none 76 | inputFormat 77 | text 78 | keyEquivalent 79 | ^h 80 | name 81 | Documentation for Word 82 | outputCaret 83 | afterOutput 84 | outputFormat 85 | text 86 | outputLocation 87 | toolTip 88 | scope 89 | source.php 90 | semanticClass 91 | lookup.define.php 92 | uuid 93 | 412481DC-89B7-11D9-9FE3-000A9584EC8C 94 | version 95 | 2 96 | 97 | 98 | -------------------------------------------------------------------------------- /Commands/PHPDoc Help.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | . "$TM_SUPPORT_PATH/lib/webpreview.sh" 9 | html_header PHPDoc 10 | 11 | Markdown.pl <<'EOF' 12 | 13 | # Snippets 14 | 15 | This bundle contains snippets for use with [PHPDoc](http://phpdoc.org/). 16 | 17 | * `doc_c ` — Class 18 | * `doc_d ` — Define inline constant 19 | * `doc_f ` — Function 20 | * `doc_h ` — Document header 21 | * `doc_i ` — Interface class 22 | * `doc_s ` — Abstract function signature 23 | * `doc_v ` — Class variable 24 | 25 | There is also a command used for adding documentation to existing entities – move the caret before a class/interface, function, define or variable and use `doc⇥`. 26 | 27 | # Shell Variables 28 | 29 | The snippets make use of two environment variables (_set these under Preferences &#x2192; Advanced &#x2192; Shell Variables_). 30 | 31 | * `TM_ORGANIZATION_NAME` — default value of @copyright [+ date] 32 | * `PHPDOC_AUTHOR` — default value of @author (realname will be used if not set) 33 | 34 | If you want docblocks to automatically wrap after 80 columns, you need to set it up: 35 | 36 | 1. Open the Bundle Editor (&#x2303;&#x2325;&#x2318;B) 37 | 2. Find and select the “Wrap Docblock at 80 Characters” command 38 | 3. Click in the white box next to “Key Equivalent” and press space 39 | 4. Close the Bundle Editor 40 | EOF 41 | input 42 | none 43 | name 44 | Help 45 | output 46 | showAsHTML 47 | scope 48 | source.php 49 | uuid 50 | EBD6D4CF-9F5E-4616-9880-5D3FF21EF408 51 | 52 | 53 | -------------------------------------------------------------------------------- /Commands/Post-doc.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby18 9 | 10 | next_line = STDIN.read.to_a[ENV['TM_LINE_NUMBER'].to_i..-1].join("\n").strip[/.+$/] 11 | 12 | puts '/**' 13 | 14 | @tags = [] 15 | type = '' 16 | author = true 17 | 18 | def tag(tag, default, trailing = nil) 19 | @tags << {:tag => tag, :default => default, :trailing => trailing} 20 | end 21 | 22 | case next_line 23 | when /(class|interface) / 24 | type = $& 25 | tag 'package', 'default' 26 | when /function\s*(\w+)\((.*)\)/ 27 | function_name, args = $1, $2 28 | type = 'function' 29 | args.split(/,/).each do |arg| 30 | arg.strip =~ /(?:(\w+)\s*)?\$([A-z0-9]+)/ 31 | tag 'param', $1 || 'string', "\\$" + $2 32 | end 33 | tag 'return', 'void' unless function_name == '__construct' 34 | when /const|define/ 35 | type = 'constant' 36 | author = false 37 | when /var|p(ublic|rivate|rotected)(\s*static)?\s*\$/ 38 | type = 'variable' 39 | tag 'var', 'string' 40 | author = false 41 | end 42 | 43 | puts " * ${1:undocumented #{type}}" 44 | puts ' *' if @tags.size > 0 or author 45 | 46 | placeholder = 1 47 | @tags.each do |tag| 48 | placeholder += 1 49 | if tag[:trailing] 50 | puts " * @#{tag[:tag]} ${#{placeholder}:#{tag[:default]}} #{tag[:trailing] } \$#{placeholder += 1}" 51 | else 52 | puts " * @#{tag[:tag]} ${#{placeholder}:#{tag[:default]}}" 53 | end 54 | end 55 | 56 | puts ' * @author ${PHPDOC_AUTHOR:$TM_FULLNAME}$' + (placeholder + 1).to_s if author 57 | print ' */$0' 58 | fallbackInput 59 | scope 60 | input 61 | document 62 | inputFormat 63 | text 64 | name 65 | Post-doc 66 | outputCaret 67 | afterOutput 68 | outputFormat 69 | snippet 70 | outputLocation 71 | replaceSelection 72 | scope 73 | source.php 74 | tabTrigger 75 | doc 76 | uuid 77 | 94D8B40B-9F49-4B6D-90B5-DBFF5FB36590 78 | version 79 | 2 80 | 81 | 82 | -------------------------------------------------------------------------------- /Commands/Run PHP.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | autoScrollOutput 6 | 7 | beforeRunningCommand 8 | nop 9 | command 10 | #!/bin/sh 11 | ruby18 -- "$TM_BUNDLE_SUPPORT/lib/php_mate.rb" 12 | input 13 | document 14 | inputFormat 15 | text 16 | keyEquivalent 17 | @R 18 | name 19 | Run 20 | outputCaret 21 | afterOutput 22 | outputFormat 23 | html 24 | outputLocation 25 | newWindow 26 | scope 27 | text.html.php 28 | semanticClass 29 | process.run.php 30 | uuid 31 | 774E75DA-A747-4CB4-B8AF-DE720B01E295 32 | version 33 | 2 34 | 35 | 36 | -------------------------------------------------------------------------------- /Commands/Special: Return Inside an Empty Tag.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env bash 9 | [[ -f "${TM_SUPPORT_PATH}/lib/bash_init.sh" ]] && . "${TM_SUPPORT_PATH}/lib/bash_init.sh" 10 | 11 | exit_insert_snippet " 12 | \$0 13 | ?" 14 | fallbackInput 15 | scope 16 | input 17 | selection 18 | inputFormat 19 | text 20 | keyEquivalent 21 | 22 | name 23 | Special: Return Inside an Empty Tag 24 | outputCaret 25 | afterOutput 26 | outputFormat 27 | snippet 28 | outputLocation 29 | replaceInput 30 | scope 31 | meta.special.empty-tag.php 32 | uuid 33 | 647C793F-9098-481B-8B5A-BCEF3B48CB03 34 | version 35 | 2 36 | 37 | 38 | -------------------------------------------------------------------------------- /Commands/Validate syntax.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby18 9 | # encoding: UTF-8 10 | require ENV['TM_SUPPORT_PATH'] + '/lib/textmate' 11 | version = %x{#{ENV['TM_PHP'] || 'php'} -v}.split[0..2].join(' ') 12 | puts "Running syntax check with " + version + "…" 13 | result = `#{ENV['TM_PHP'] || 'php'} -d display_errors=on -l` 14 | puts result.gsub('in -', '') 15 | TextMate.go_to :line => $1 if result =~ /line (\d+)/ 16 | input 17 | document 18 | keyEquivalent 19 | ^V 20 | name 21 | Validate Syntax 22 | output 23 | showAsTooltip 24 | scope 25 | source.php 26 | uuid 27 | EC271DAE-BEC9-11D9-8856-000D93589AF6 28 | 29 | 30 | -------------------------------------------------------------------------------- /Commands/Wrap Docblock at 80 Characters.tmCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | #!/usr/bin/env ruby18 9 | col = ENV['TM_COLUMN_NUMBER'].to_i 10 | start_col = ENV['TM_CURRENT_LINE'].index('*') 11 | if col - start_col >= 80 12 | puts 13 | print " " * start_col + "*" 14 | end 15 | print " " 16 | input 17 | none 18 | name 19 | Wrap Docblock at 80 Characters 20 | output 21 | afterSelectedText 22 | scope 23 | comment.block.documentation.phpdoc.php 24 | uuid 25 | 6F7E7868-F5A2-4B7D-ACFB-2A8DE2CD04E2 26 | 27 | 28 | -------------------------------------------------------------------------------- /DragCommands/Include dropped file.tmDragCommand: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | beforeRunningCommand 6 | nop 7 | command 8 | ruby18 <<-'RUBY' 9 | # Stores all the possible paths to the dropped file 10 | paths = [] 11 | 12 | # Include the relative path as given by TM as a default 13 | # Possibly this should be disabled to favour absolute paths? 14 | paths << ENV['TM_DROPPED_FILE'] 15 | if ENV['PHP_INCLUDE_PATH'] 16 | ENV['PHP_INCLUDE_PATH'].split(':').each do |dir| 17 | dir << '/' 18 | # Check each directory in the include path to see if it prefixes the requested file 19 | if ENV['TM_DROPPED_FILEPATH'][0, dir.size] == dir 20 | # If it matches, store the path to the file from this include directory 21 | paths << ENV['TM_DROPPED_FILEPATH'][dir.size..-1] 22 | end 23 | end 24 | end 25 | 26 | include_method = ENV['TM_MODIFIER_FLAGS'].include?('CONTROL') ? 'require' : 'include' 27 | 28 | include_method << '_once' if ENV['TM_MODIFIER_FLAGS'].include?('OPTION') 29 | 30 | # Find the shortest path 31 | path = paths.sort_by{|path| path.size}.reverse.pop 32 | puts "#{include_method} '#{path}';" 33 | RUBY 34 | draggedFileExtensions 35 | 36 | php 37 | inc 38 | 39 | input 40 | selection 41 | name 42 | Include dropped file 43 | output 44 | insertAsSnippet 45 | scope 46 | source.php 47 | uuid 48 | B5E34751-D5EB-4AC8-9DB1-779BD6489C76 49 | 50 | 51 | -------------------------------------------------------------------------------- /Preferences/Add Magic Methods to the Symbol List.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Add Magic Methods to the Symbol List 7 | scope 8 | support.function.magic.php 9 | settings 10 | 11 | showInSymbolList 12 | 1 13 | 14 | uuid 15 | 77F2D17D-A48A-4E19-B2A4-B2FBCBD1264D 16 | 17 | 18 | -------------------------------------------------------------------------------- /Preferences/Add goto labels to symbol list.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Add goto labels to symbol list 7 | scope 8 | entity.name.goto-label.php 9 | settings 10 | 11 | showInSymbolList 12 | 1 13 | symbolTransformation 14 | s/$/:/a 15 | 16 | uuid 17 | 998BFB01-C049-4A24-A88E-86173C967748 18 | 19 | 20 | -------------------------------------------------------------------------------- /Preferences/Comments.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Comments 7 | scope 8 | source.php 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_START_3 28 | value 29 | /* 30 | 31 | 32 | name 33 | TM_COMMENT_END_3 34 | value 35 | */ 36 | 37 | 38 | 39 | uuid 40 | 06276449-AA4E-424F-A2B6-9F4138416E50 41 | 42 | 43 | -------------------------------------------------------------------------------- /Preferences/Completion: includes.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Completion: includes 7 | scope 8 | meta.include.php string.quoted 9 | settings 10 | 11 | completionCommand 12 | ruby18 <<-'RUBY' 13 | path = ENV["TM_CURRENT_LINE"].to_s[0..ENV["TM_COLUMN_NUMBER"].to_i-1].to_s[/['"]([^'"]+)['"]/,1].to_s + "*" 14 | Dir::chdir(File.dirname(ENV["TM_FILEPATH"])) if ENV["TM_FILEPATH"] 15 | include_paths = ENV["PHP_INCLUDE_PATH"] ? ENV["PHP_INCLUDE_PATH"].split(":") : ["."] 16 | matches = include_paths.inject([]) do |res, include_path| 17 | include_path << "/" unless include_path[-1] == ?/ 18 | res + Dir.glob(include_path + path).map {|file| 19 | file[include_path.size..-1][/[^\/]+$/] + (File.directory?(file) ? "/" : "") 20 | } 21 | end 22 | puts matches.sort.uniq.join("\n") 23 | RUBY 24 | disableDefaultCompletion 25 | 1 26 | 27 | uuid 28 | CBE2288F-76FC-4813-B69B-B90FFAE3391C 29 | 30 | 31 | -------------------------------------------------------------------------------- /Preferences/Disable spellcheck in require.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Disable spellcheck in require 7 | scope 8 | meta.include.php string.quoted 9 | settings 10 | 11 | spellChecking 12 | 0 13 | 14 | uuid 15 | FD4397A8-415F-47BC-9F8D-E0F0EC364286 16 | 17 | 18 | -------------------------------------------------------------------------------- /Preferences/Enable Spellchecking for Docblocks.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Enable Spellchecking for Docblocks 7 | scope 8 | comment.block.documentation.phpdoc.php 9 | settings 10 | 11 | spellChecking 12 | 1 13 | 14 | uuid 15 | E2D08D2E-A99C-4F3A-9B1D-05A75D37A819 16 | 17 | 18 | -------------------------------------------------------------------------------- /Preferences/Folding.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Folding 7 | scope 8 | text.html.php 9 | settings 10 | 11 | foldingStartMarker 12 | (?x) 13 | (<(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|li|form|dl|section|article|header|footer|nav|aside)\b.*?> 14 | |<!--(?!.*--\s*>) 15 | |^<!--\ \#tminclude\ (?>.*?-->)$ 16 | |<\?(?:php)?.*\b(if|for(each)?|while)\b.+: 17 | |\{\{?(if|foreach|capture|literal|foreach|php|section|strip) 18 | |\{\s*($|\?>\s*$|//|/\*(.*\*/\s*$|(?!.*?\*/))) 19 | |array\s?\(\s*$ 20 | |\[\s*$ 21 | ) 22 | foldingStopMarker 23 | (?x) 24 | (</(?i:head|body|table|thead|tbody|tfoot|tr|div|select|fieldset|style|script|ul|ol|li|form|dl|section|article|header|footer|nav|aside)> 25 | |^(?!.*?<!--).*?--\s*> 26 | |^<!--\ end\ tminclude\ -->$ 27 | |<\?(?:php)?.*\bend(if|for(each)?|while)\b 28 | |\{\{?/(if|foreach|capture|literal|foreach|php|section|strip) 29 | |^[^{]*\} 30 | |^\s*\)[,;] 31 | |^\s*\][,;] 32 | ) 33 | 34 | uuid 35 | 7F5C8332-CEE9-4A30-A3A1-54F36AF45C38 36 | 37 | 38 | -------------------------------------------------------------------------------- /Preferences/Indentation Arrays.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Indentation: Arrays 7 | scope 8 | source.php meta.array.php 9 | settings 10 | 11 | decreaseIndentPattern 12 | (?x) 13 | ^ (.* \*/)? \s* 14 | (\)+) 15 | 16 | 17 | uuid 18 | 58096C41-EA70-488D-A163-8CD4C687B301 19 | 20 | 21 | -------------------------------------------------------------------------------- /Preferences/Indentation Rules.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Indentation Rules 7 | scope 8 | source.php -string 9 | settings 10 | 11 | decreaseIndentPattern 12 | (?x) 13 | ^ (.* \*/)? \s* 14 | ( 15 | (\}) | 16 | (\)+[;,]) | 17 | (\][;,]) | 18 | \b (else:) | 19 | \b ((end(if|for(each)?|while|switch));) 20 | ) 21 | 22 | increaseIndentPattern 23 | (?x) 24 | ( \{ (?! .+ \} ) .* 25 | | \b array\( 26 | | (\[) 27 | | \b ((else)?if|else|for(each)?|while|switch) .* : 28 | ) \s* (/[/*] .*)? $ 29 | indentNextLinePattern 30 | (?x)^ 31 | (?! .*? (<\?|\?>) ) 32 | (?! \s* ($|//|/\*|\#)) 33 | (?! .* [;:{}(,] \s* ((//|/\*|\#).*)? $) 34 | 35 | unIndentedLinePattern 36 | ^\s*$ 37 | 38 | uuid 39 | CA15DF69-E80D-46DA-BD45-E88C68E92117 40 | 41 | 42 | -------------------------------------------------------------------------------- /Preferences/Miscellaneous.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Miscellaneous 7 | scope 8 | source.php 9 | settings 10 | 11 | highlightPairs 12 | 13 | 14 | ( 15 | ) 16 | 17 | 18 | { 19 | } 20 | 21 | 22 | [ 23 | ] 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | uuid 32 | F15B444C-13E3-4A3C-83E1-4A6E0C1A84F3 33 | 34 | 35 | -------------------------------------------------------------------------------- /Preferences/Symbols List: functions.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Symbols List: Indent Functions 7 | scope 8 | entity.name.function.php, support.function.magic.php 9 | settings 10 | 11 | symbolTransformation 12 | 13 | s/^/ /; # pad 14 | 15 | 16 | uuid 17 | 5157F71C-2801-4385-92EA-3D0B72AEE7C5 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.mdown: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | You can install this bundle in TextMate by opening the preferences and going to the bundles tab. After installation it will be automatically updated for you. 4 | 5 | # General 6 | 7 | * [Bundle Styleguide](http://kb.textmate.org/bundle_styleguide) — _before you make changes_ 8 | * [Commit Styleguide](http://kb.textmate.org/commit_styleguide) — _before you send a pull request_ 9 | * [Writing Bug Reports](http://kb.textmate.org/writing_bug_reports) — _before you report an issue_ 10 | 11 | # License 12 | 13 | If not otherwise specified (see below), files in this repository fall under the following license: 14 | 15 | Permission to copy, use, modify, sell and distribute this 16 | software is granted. This software is provided "as is" without 17 | express or implied warranty, and with no claim as to its 18 | suitability for any purpose. 19 | 20 | An exception is made for files in readable text which contain their own license information, or files where an accompanying file exists (in the same directory) with a “-license” suffix added to the base-name name of the original file, and an extension of txt, html, or similar. For example “tidy” is accompanied by “tidy-license.txt”. -------------------------------------------------------------------------------- /Snippets/$GLOBALS[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$GLOBALS['${1:variable}']${2: = }${3:something}${4:;}$0 7 | name 8 | $GLOBALS['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | globals 13 | uuid 14 | E8BDF86F-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_COOKIE[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_COOKIE['${1:variable}'] 7 | name 8 | COOKIE['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | 9B253562-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_ENV[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_ENV['${1:variable}'] 7 | name 8 | ENV['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | B90F3AE5-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_FILES[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_FILES['${1:variable}'] 7 | name 8 | FILES['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | FF0A8A5C-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_GET[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_GET['${1:variable}'] 7 | name 8 | GET['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | CF29C6B5-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_POST[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_POST['${1:variable}'] 7 | name 8 | POST['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | 4E18C61F-8CD1-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_REQUEST[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_REQUEST['${1:variable}'] 7 | name 8 | REQUEST['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | 19B4F695-8CD1-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_SERVER[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_SERVER['${1:variable}'] 7 | name 8 | SERVER['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | 306E5B79-8CD1-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/$_SESSION[''].tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$_SESSION['${1:variable}'] 7 | name 8 | SESSION['…'] 9 | scope 10 | source.php 11 | tabTrigger 12 | $_ 13 | uuid 14 | 40A7709D-8CD1-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/… ?>.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG:php} \$this->$0 ?> 7 | name 8 | <?php $this->… ?> 9 | scope 10 | text.html.php - source 11 | tabTrigger 12 | this 13 | uuid 14 | 5F800F2D-55DA-4E06-99A3-41B734C8768E 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG:php} $0 ?> 7 | name 8 | <?php … ?> 9 | scope 10 | text.html.php, L:dyn.caret.begin.document 11 | tabTrigger 12 | php 13 | uuid 14 | BB471E3A-8CCD-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/… ?>.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG_WITH_ECHO:php echo} \$this->$0 ?> 7 | name 8 | <?php echo $this->… ?> 9 | scope 10 | text.html.php - source 11 | tabTrigger 12 | ethis 13 | uuid 14 | 7553818C-6FF8-455D-BD83-D2A587BAF6F4 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG_WITH_ECHO:php echo} ${1:\$var} ?>$0 7 | name 8 | <?php echo … ?> 9 | scope 10 | text.html.php 11 | tabTrigger 12 | echo 13 | uuid 14 | 117476CE-7A7F-4DC4-9A4E-772D282983A3 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG_WITH_ECHO:php echo} htmlentities(${1:\$var}, ENT_QUOTES, 'utf-8') ?>$0 7 | name 8 | <?php echo htmlentities(…) ?> 9 | scope 10 | text.html.php 11 | tabTrigger 12 | echoh 13 | uuid 14 | ED759470-69D7-4ADF-9842-D890DEB00F19 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG:php} else: ?> 7 | name 8 | <?php else: ?> 9 | scope 10 | text.html.php 11 | tabTrigger 12 | else 13 | uuid 14 | 3F335934-360B-40F2-9D5C-CB299FD2F215 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG:php} foreach (\$${1:variable} as \$${2:key}${3: => \$${4:value}}): ?> 7 | ${0} 8 | <?${TM_PHP_OPEN_TAG:php} endforeach ?> 9 | name 10 | <?php foreach (…) … <?php endforeach ?> 11 | scope 12 | text.html.php 13 | tabTrigger 14 | foreach 15 | uuid 16 | 1E34E416-CD16-4C16-A369-9CDC3FAFD4C4 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/ ___ ___ .tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG:php} if (${1:condition}): ?> 7 | $2 8 | <?${TM_PHP_OPEN_TAG:php} else: ?> 9 | $0 10 | <?${TM_PHP_OPEN_TAG:php} endif ?> 11 | name 12 | <?php if (…) ?> … <?php else ?> … <?php endif ?> 13 | scope 14 | text.html.php 15 | tabTrigger 16 | ifelse 17 | uuid 18 | E863B097-0FD5-43D5-8547-235330081203 19 | 20 | 21 | -------------------------------------------------------------------------------- /Snippets/ ___ .tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <?${TM_PHP_OPEN_TAG:php} if (${1:condition}): ?> 7 | $0 8 | <?${TM_PHP_OPEN_TAG:php} endif ?> 9 | name 10 | <?php if (…) ?> … <?php endif ?> 11 | scope 12 | text.html.php 13 | tabTrigger 14 | if 15 | uuid 16 | 4F33617A-80FE-47D2-84AF-AA3D5D8A7128 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/?>… 2 | 3 | 4 | 5 | content 6 | ?>$0<?${TM_PHP_OPEN_TAG:php} 7 | keyEquivalent 8 | ^> 9 | name 10 | ?>…<?php 11 | scope 12 | source.php 13 | tabTrigger 14 | php 15 | uuid 16 | C1B97DFD-7F2E-4CF8-881D-F63843DE8BD5 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Constructor.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | function __construct(${1:\$${2:foo}${3: = ${4:null}}}) { 7 | ${2/.+/$this->$0 = \$$0;/}$0 8 | } 9 | name 10 | function __construct 11 | scope 12 | source.php 13 | tabTrigger 14 | con 15 | uuid 16 | DF786227-F5C9-48A1-8C80-49306AE82B6A 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Continue Block Comment.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | ${TM_CURRENT_LINE/(.*\*\/$)|.*?(\/\*(?!.*\*\/)).*|.*/(?1: 7 | : 8 | (?2: )* )/} 9 | keyEquivalent 10 |  11 | name 12 | Continue Block Comment 13 | scope 14 | source.php comment.block 15 | uuid 16 | 26BC937A-5A0B-493E-B51F-1AF6E6FEFAD4 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Heredoc.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | <<<${1:HTML} 7 | ${2:content here} 8 | $1; 9 | 10 | name 11 | Heredoc 12 | scope 13 | source.php 14 | tabTrigger 15 | <<< 16 | uuid 17 | 1634287E-035A-4617-9AD8-09133183F8FE 18 | 19 | 20 | -------------------------------------------------------------------------------- /Snippets/Include TextMate Support Script.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | // === TextMate error handling === 7 | `if [[ "$TM_BUNDLE_SUPPORT" == "$HOME"* ]]; then 8 | echo "// NOTE: Your PHP bundle is checked out to your home directory." 9 | echo "// If the webserver process does not have permission to access" 10 | echo "// the included file, you can replace" 11 | echo "// ‘${TM_BUNDLE_SUPPORT%Bundles*}’ with" 12 | echo "// ‘$(find_app TextMate.app)/Contents/SharedSupport/’." 13 | fi` 14 | @include_once '$TM_BUNDLE_SUPPORT/textmate.php'; 15 | 16 | name 17 | Include TextMate Support Script 18 | scope 19 | source.php 20 | tabTrigger 21 | tmphp 22 | uuid 23 | 6F3ABAC6-EEC9-4797-8D4A-6FD549094852 24 | 25 | 26 | -------------------------------------------------------------------------------- /Snippets/PHP Error Catching.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | `cat "$TM_BUNDLE_SUPPORT/textmate_error_handler.html" | grep -E -v '^[ \t\s]*\/\/' | sed 's/\(.*\)[ \t]*--.*/\1/' | tr -s ' \n\t' ' ' | sed 's/.\{80\}[{};]/&\ 7 | /g'` 8 | name 9 | PHP Error Catching JavaScript 10 | scope 11 | text.html.php 12 | tabTrigger 13 | phperr 14 | uuid 15 | 9C891C7B-CFA8-4860-B76F-4E3AD60B0E13 16 | 17 | 18 | -------------------------------------------------------------------------------- /Snippets/PHPDoc class var.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundlePath 6 | /Users/kumar/Library/Application Support/TextMate/Bundles/PHPDoc.tmbundle 7 | content 8 | /** 9 | * ${3:undocumented class variable} 10 | * 11 | * @var ${4:string} 12 | */ 13 | ${1:var} \$$2;$0 14 | name 15 | Class Variable 16 | scope 17 | source.php 18 | tabTrigger 19 | doc_v 20 | uuid 21 | 90879700-87E7-11D9-A6A3-000D93589AF6 22 | 23 | 24 | -------------------------------------------------------------------------------- /Snippets/PHPDoc class.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundlePath 6 | /Users/kumar/Library/Application Support/TextMate/Bundles/PHPDoc.tmbundle 7 | content 8 | /** 9 | * ${3:undocumented class} 10 | * 11 | * @package ${4:default} 12 | * @author ${PHPDOC_AUTHOR:$TM_FULLNAME} 13 | */ 14 | $1class $2 15 | {$0 16 | } // END $1class $2 17 | name 18 | Class 19 | scope 20 | source.php 21 | tabTrigger 22 | doc_c 23 | uuid 24 | 9086BA3F-87E7-11D9-A6A3-000D93589AF6 25 | 26 | 27 | -------------------------------------------------------------------------------- /Snippets/PHPDoc constant definition.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundlePath 6 | /Users/kumar/Library/Application Support/TextMate/Bundles/PHPDoc.tmbundle 7 | content 8 | /** 9 | * ${3:undocumented constant} 10 | */ 11 | define($1, $2);$0 12 | name 13 | Constant Definition 14 | scope 15 | source.php 16 | tabTrigger 17 | doc_d 18 | uuid 19 | 9086E254-87E7-11D9-A6A3-000D93589AF6 20 | 21 | 22 | -------------------------------------------------------------------------------- /Snippets/PHPDoc function signature.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundlePath 6 | /Users/kumar/Library/Application Support/TextMate/Bundles/PHPDoc.tmbundle 7 | content 8 | /** 9 | * ${4:undocumented function} 10 | * 11 | * @return ${5:void} 12 | * @author ${PHPDOC_AUTHOR:$TM_FULLNAME}$6 13 | */ 14 | $1function $2($3);$0 15 | keyEquivalent 16 | 17 | name 18 | Function Signature 19 | scope 20 | source.php 21 | tabTrigger 22 | doc_s 23 | uuid 24 | 908774B1-87E7-11D9-A6A3-000D93589AF6 25 | 26 | 27 | -------------------------------------------------------------------------------- /Snippets/PHPDoc function.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundlePath 6 | /Users/kumar/Library/Application Support/TextMate/Bundles/PHPDoc.tmbundle 7 | content 8 | /** 9 | * ${4:undocumented function} 10 | * 11 | * @return ${5:void} 12 | * @author ${PHPDOC_AUTHOR:$TM_FULLNAME}$6 13 | */ 14 | $1function $2($3) 15 | {$0 16 | } 17 | name 18 | Function 19 | scope 20 | source.php 21 | tabTrigger 22 | doc_f 23 | uuid 24 | 9087051B-87E7-11D9-A6A3-000D93589AF6 25 | 26 | 27 | -------------------------------------------------------------------------------- /Snippets/PHPDoc header.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundlePath 6 | /Users/kumar/Library/Application Support/TextMate/Bundles/PHPDoc.tmbundle 7 | content 8 | /** 9 | * $1 10 | * 11 | * @author ${PHPDOC_AUTHOR:$TM_FULLNAME} 12 | * @version \$Id\$ 13 | * @copyright `echo $TM_ORGANIZATION_NAME`, `date +"%e %B, %Y" | sed 's/^ //'` 14 | * @package ${3:default} 15 | */ 16 | 17 | /** 18 | * Define DocBlock 19 | */ 20 | 21 | name 22 | Header 23 | scope 24 | source.php 25 | tabTrigger 26 | doc_h 27 | uuid 28 | 90872B90-87E7-11D9-A6A3-000D93589AF6 29 | 30 | 31 | -------------------------------------------------------------------------------- /Snippets/PHPDoc interface.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundlePath 6 | /Users/kumar/Library/Application Support/TextMate/Bundles/PHPDoc.tmbundle 7 | content 8 | /** 9 | * ${2:undocumented class} 10 | * 11 | * @package ${3:default} 12 | * @author ${PHPDOC_AUTHOR:$TM_FULLNAME} 13 | */ 14 | interface $1 15 | {$0 16 | } // END interface $1 17 | name 18 | Interface 19 | scope 20 | source.php 21 | tabTrigger 22 | doc_i 23 | uuid 24 | 90874D6F-87E7-11D9-A6A3-000D93589AF6 25 | 26 | 27 | -------------------------------------------------------------------------------- /Snippets/Special: Return Between PHP Tags.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | 7 | $0 8 | 9 | keyEquivalent 10 | 11 | name 12 | Special: Return Between PHP Tags 13 | scope 14 | L:(meta.embedded.*.php punctuation.section.embedded.end.php) & R:(meta.embedded.line.php punctuation.section.embedded.*.php) 15 | uuid 16 | 89385241-0117-42AE-BDAE-0471554CC3DF 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Special: Return Inside an Array.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | 7 | $0 8 | 9 | keyEquivalent 10 | 11 | name 12 | Special: Return Inside an Array 13 | scope 14 | meta.array.empty.php punctuation.definition.array.end.php 15 | uuid 16 | E0FF5942-5249-4097-A4EE-E01FAE518CD2 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/Start Docblock.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | /** 7 | * $0 8 | */ 9 | name 10 | Start Docblock 11 | scope 12 | source.php 13 | tabTrigger 14 | /** 15 | uuid 16 | 775F7FCC-C43C-4C23-B935-9D5F6C25CF1D 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/class { }.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | ${1/.+/\/**\n* /}${1:Description}${1/.+/\n*\/\n/}class ${2:ClassName}${3: extends ${4:AnotherClass}} 7 | { 8 | $5 9 | function ${6:__construct}(${7:argument}) 10 | { 11 | ${0:# code...} 12 | } 13 | } 14 | name 15 | class … 16 | scope 17 | source.php 18 | tabTrigger 19 | class 20 | uuid 21 | 0F39268F-8CD0-11D9-B507-000D93C8BE28 22 | 23 | 24 | -------------------------------------------------------------------------------- /Snippets/define( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | define('$1', ${2:'$3'}); 7 | $0 8 | name 9 | define(…, …) 10 | scope 11 | source.php 12 | tabTrigger 13 | def 14 | uuid 15 | 8AAEC70A-8CCF-11D9-B507-000D93C8BE28 16 | 17 | 18 | -------------------------------------------------------------------------------- /Snippets/defined( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | $1defined('$2')$0 7 | name 8 | defined(…) 9 | scope 10 | source.php 11 | tabTrigger 12 | def? 13 | uuid 14 | A94E02E2-8CCF-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/do while( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | do { 7 | ${0:# code...} 8 | } while (${1:$a <= 10}); 9 | name 10 | do … while … 11 | scope 12 | source.php 13 | tabTrigger 14 | do 15 | uuid 16 | 1C06D786-8CCF-11D9-B507-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/echo ___.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | echo "${1:string}"${0}; 7 | name 8 | echo "…" 9 | scope 10 | source.php 11 | tabTrigger 12 | echo 13 | uuid 14 | 2B91DE5F-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/else {}.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | else { 7 | ${0:# code...} 8 | } 9 | name 10 | else … 11 | scope 12 | source.php 13 | tabTrigger 14 | else 15 | uuid 16 | 609FE8EB-B251-11D9-872D-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/elseif( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | elseif (${1:condition}) { 7 | ${0:# code...} 8 | } 9 | name 10 | elseif … 11 | scope 12 | source.php 13 | tabTrigger 14 | elseif 15 | uuid 16 | 61DCF7E4-8CCE-11D9-B507-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/for( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | for (\$${1:i}=${2:0}; \$${1:i} < $3; \$${1:i}++) { 7 | ${0:# code...} 8 | } 9 | name 10 | for … 11 | scope 12 | source.php 13 | tabTrigger 14 | for 15 | uuid 16 | AC5561AA-8CCE-11D9-B507-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/foreach( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | foreach (\$${1:variable} as \$${2:key}${3: => \$${4:value}}) { 7 | ${0:# code...} 8 | } 9 | name 10 | foreach … 11 | scope 12 | source.php 13 | tabTrigger 14 | foreach 15 | uuid 16 | C0229432-8CCE-11D9-B507-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/function xx( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | ${1|public,private,protected|}${1/.+/ /}function ${2:FunctionName}(${3:\$${4:value}${5:=''}}) 7 | { 8 | ${0:# code...} 9 | } 10 | name 11 | function … 12 | scope 13 | source.php 14 | tabTrigger 15 | fun 16 | uuid 17 | EC96DA26-8CCF-11D9-B507-000D93C8BE28 18 | 19 | 20 | -------------------------------------------------------------------------------- /Snippets/if ?: a : b;.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b} ; 7 | name 8 | $… = ( … ) ? … : … 9 | scope 10 | source.php 11 | tabTrigger 12 | if? 13 | uuid 14 | 7720523B-8CCE-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/if( ) else( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if (${1:condition}) { 7 | ${2:# code...} 8 | } else { 9 | ${3:# code...} 10 | } 11 | $0 12 | name 13 | if … else … 14 | scope 15 | source.php 16 | tabTrigger 17 | ifelse 18 | uuid 19 | 4B72EA1F-8CCE-11D9-B507-000D93C8BE28 20 | 21 | 22 | -------------------------------------------------------------------------------- /Snippets/if( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | if (${1:condition}) { 7 | ${0:# code...} 8 | } 9 | name 10 | if … 11 | scope 12 | source.php 13 | tabTrigger 14 | if 15 | uuid 16 | 35F46C2E-8CCE-11D9-B507-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/include( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | include '${1:file}';$0 7 | name 8 | include … 9 | scope 10 | source.php 11 | tabTrigger 12 | incl 13 | uuid 14 | 34E2C808-8CCF-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/include_once( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | include_once '${1:file}';$0 7 | name 8 | include_once … 9 | scope 10 | source.php 11 | tabTrigger 12 | incl1 13 | uuid 14 | 4833C612-8CCF-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/new array( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | \$${1:arrayName} = array('$2' => $3${4:,} $0); 7 | name 8 | $… = array (…) 9 | scope 10 | source.php 11 | tabTrigger 12 | array 13 | uuid 14 | CBF8F204-8CCF-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/require( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | require '${1:file}';$0 7 | name 8 | require … 9 | scope 10 | source.php 11 | tabTrigger 12 | req 13 | uuid 14 | 60129434-8CCF-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/require_once( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | require_once '${1:file}';$0 7 | name 8 | require_once … 9 | scope 10 | source.php 11 | tabTrigger 12 | req1 13 | uuid 14 | 6E25DCEF-8CCF-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/return $retVal;.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | return$1;$0 7 | name 8 | return 9 | scope 10 | source.php 11 | tabTrigger 12 | ret 13 | uuid 14 | 80D861BF-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/return FALSE;.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | return false;$0 7 | name 8 | return false 9 | scope 10 | source.php 11 | tabTrigger 12 | ret0 13 | uuid 14 | 56873C6E-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/return TRUE;.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | return true;$0 7 | name 8 | return true 9 | scope 10 | source.php 11 | tabTrigger 12 | ret1 13 | uuid 14 | 459B8A24-8CD0-11D9-B507-000D93C8BE28 15 | 16 | 17 | -------------------------------------------------------------------------------- /Snippets/switch( ) case:.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | case '${1:variable}': 7 | ${0:# code...} 8 | break; 9 | name 10 | case … 11 | scope 12 | source.php 13 | tabTrigger 14 | case 15 | uuid 16 | F262B1FA-8CCE-11D9-B507-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Snippets/switch( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | switch (${1:variable}) { 7 | case '${2:value}': 8 | ${3:# code...} 9 | break; 10 | $0 11 | default: 12 | ${4:# code...} 13 | break; 14 | } 15 | name 16 | switch … 17 | scope 18 | source.php 19 | tabTrigger 20 | switch 21 | uuid 22 | DA4B6728-8CCE-11D9-B507-000D93C8BE28 23 | 24 | 25 | -------------------------------------------------------------------------------- /Snippets/throw.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | throw new $1Exception(${2:"${3:Error Processing Request}"}${4:, ${5:1}}); 7 | $0 8 | name 9 | Throw Exception 10 | scope 11 | source.php 12 | tabTrigger 13 | throw 14 | uuid 15 | FE39640E-A69C-48DF-9282-633672AAEFD2 16 | 17 | 18 | -------------------------------------------------------------------------------- /Snippets/try { ___ } catch (___) { ___ }.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | ${TM_SELECTED_TEXT/([\t ]*).*/$1/m}try { 7 | ${3:${TM_SELECTED_TEXT/(\A.*)|(.+)|\n\z/(?1:$0:(?2:\t$0))/g}} 8 | ${TM_SELECTED_TEXT/([\t ]*).*/$1/m}} catch (${1:Exception} ${2:\$e}) { 9 | ${TM_SELECTED_TEXT/([\t ]*).*/$1/m} $0 10 | ${TM_SELECTED_TEXT/([\t ]*).*/$1/m}} 11 | keyEquivalent 12 | ^@W 13 | name 14 | Wrap in try { … } catch (…) { … } 15 | scope 16 | source.php 17 | tabTrigger 18 | try 19 | uuid 20 | F7751DAF-AC95-4D47-955F-FE2534FDE4F5 21 | 22 | 23 | -------------------------------------------------------------------------------- /Snippets/while( ).tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | while (${1:$a <= 10}) { 7 | ${0:# code...} 8 | } 9 | name 10 | while … 11 | scope 12 | source.php 13 | tabTrigger 14 | while 15 | uuid 16 | 0D955946-8CCF-11D9-B507-000D93C8BE28 17 | 18 | 19 | -------------------------------------------------------------------------------- /Support/documentation.txt: -------------------------------------------------------------------------------- 1 | # This file is used to map words to PHP manual URLs 2 | 3 | # Control structures 4 | else=control-structures.else 5 | elseif=control-structures.elseif 6 | while=control-structures.while 7 | do=control-structures.do.while 8 | for=control-structures.for 9 | foreach=control-structures.foreach 10 | break=control-structures.break 11 | continue=control-structures.continue 12 | switch=control-structures.switch 13 | case=control-structures.switch 14 | declare=control-structures.declare 15 | if=language.control-structures 16 | 17 | # Constants 18 | __line__=language.constants.predefined 19 | __file__=language.constants.predefined 20 | __dir__=language.constants.predefined 21 | __function__=language.constants.predefined 22 | __class__=language.constants.predefined 23 | __method__=language.constants.predefined 24 | __namespace__=language.constants.predefined 25 | 26 | # OOP 27 | new=language.oop5.basic 28 | class=language.oop5.basic 29 | extends=language.oop5.basic 30 | construct=language.oop5.decon 31 | destruct=language.oop5.decon 32 | public=language.oop5.visibility 33 | private=language.oop5.visibility 34 | protected=language.oop5.visibility 35 | abstract=language.oop5.abstract 36 | interface=language.oop5.interfaces 37 | interfaces=language.oop5.interfaces 38 | autoload=language.oop5.autoload 39 | __autoload=language.oop5.autoload 40 | reflection=language.oop5.reflection 41 | ::=language.oop5.paamayim.nekudotayim 42 | parent=keyword.parent 43 | final=language.oop5.final 44 | abstract=language.oop5.abstract 45 | 46 | # Exceptions 47 | try=language.exceptions 48 | catch=language.exceptions 49 | throw=language.exceptions 50 | 51 | # Language internals 52 | function=language.functions 53 | global=language.variables.scope 54 | 55 | # Types 56 | number=language.pseudo-types 57 | mixed=language.pseudo-types 58 | bool=language.types.boolean 59 | boolean=language.types.boolean 60 | int=language.types.integer 61 | integer=language.types.integer 62 | float=language.types.float 63 | string=language.types.string 64 | heredoc=language.types.string 65 | <<<=language.types.string 66 | object=language.types.object 67 | null=language.types.null 68 | 69 | # Streams 70 | php_stream_stat_path=streams.php-stream-stat-path 71 | php_stream_stat=streams.php-stream-stat 72 | php_stream_open_wrapper=streams.php-stream-open-wrapper 73 | php_stream_read=streams.php-stream-read 74 | php_stream_write=streams.php-stream-write 75 | php_stream_eof=streams.php-stream-eof 76 | php_stream_getc=streams.php-stream-getc 77 | php_stream_gets=streams.php-stream-gets 78 | php_stream_close=streams.php-stream-close 79 | php_stream_flush=streams.php-stream-flush 80 | php_stream_seek=streams.php-stream-seek 81 | php_stream_tell=streams.php-stream-tell 82 | php_stream_copy_to_stream=streams.php-stream-copy-to-stream 83 | php_stream_copy_to_mem=streams.php-stream-copy-to-mem 84 | php_stream_make_seekable=streams.php-stream-make-seekable 85 | php_stream_cast=streams.php-stream-cast 86 | php_stream_can_cast=streams.php-stream-can-cast 87 | php_stream_is_persistent=streams.php-stream-is-persistent 88 | php_stream_is=streams.php-stream-is 89 | php_stream_passthru=streams.php-stream-passthru 90 | php_register_url_stream_wrapper=streams.php-register-url-stream-wrapper 91 | php_unregister_url_stream_wrapper=streams.php-unregister-url-stream-wrapper 92 | php_stream_open_wrapper_ex=streams.php-stream-open-wrapper-ex 93 | php_stream_open_wrapper_as_file=streams.php-stream-open-wrapper-as-file 94 | php_stream_filter_register_factory=streams.php-stream-filter-register-factory 95 | php_stream_filter_unregister_factory=streams.php-stream-filter-unregister-factory 96 | php_stream_opendir=streams.php-stream-opendir 97 | php_stream_readdir=streams.php-stream-readdir 98 | php_stream_rewinddir=streams.php-stream-rewinddir 99 | php_stream_closedir=streams.php-stream-closedir 100 | php_stream_fopen_from_file=streams.php-stream-fopen-from-file 101 | php_stream_fopen_tmpfile=streams.php-stream-fopen-tmpfile 102 | php_stream_fopen_temporary_file=streams.php-stream-fopen-temporary-file 103 | php_stream_sock_open_from_socket=streams.php-stream-sock-open-from-socket 104 | php_stream_sock_open_host=streams.php-stream-sock-open-host 105 | php_stream_sock_open_unix=streams.php-stream-sock-open-unix 106 | 107 | # Support classes 108 | dir=class.dir 109 | 110 | # Misc 111 | _=function.gettext 112 | -------------------------------------------------------------------------------- /Support/generate/generate.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php -q 2 | 7 | * Example: php generate.php en 8 | * 9 | * Some languages may require memory_limit to 256MB in php.ini 10 | * 11 | * This script will produce/modify the following files: 12 | * - Support/functions.plist 13 | * - Support/function-docs/.txt 14 | * - Preferences/Completions.tmPreferences 15 | * - Syntaxes/PHP.plist 16 | */ 17 | 18 | if (2 !== $argc) { 19 | printUsage('Must specify a two-letter language code (e.g., "en")'); 20 | } else if (2 !== strlen($argv[1])) { 21 | printUsage('Language must be a two-letter code (e.g., "en")'); 22 | } 23 | 24 | $lang = strtolower($argv[1]); 25 | 26 | $excludeSections = array( 27 | 'basic.other.geoip', 28 | 'basic.other.judy', 29 | 'basic.other.parsekit', 30 | 'basic.other.yaml', 31 | 'basic.php.apd', 32 | 'basic.php.bcompiler', 33 | 'basic.php.inclued', 34 | 'basic.php.runkit', 35 | 'basic.php.wincache', 36 | 'basic.session.msession', 37 | 'basic.session.session-pgsql', 38 | 'basic.text.bbcode', 39 | 'basic.text.ssdeep', 40 | 'basic.vartype.classkit', 41 | 'compression.lzf', 42 | 'compression.rar', 43 | 'creditcard.mcve', 44 | 'creditcard.spplus', 45 | 'crypto.crack', 46 | 'database.vendors.cubrid', 47 | 'database.vendors.dbase', 48 | 'database.vendors.dbplus', 49 | 'database.vendors.fbsql', 50 | 'database.vendors.filepro', 51 | 'database.vendors.ibm-db2', 52 | 'database.vendors.ifx', 53 | 'database.vendors.ingres', 54 | 'database.vendors.maxdb', 55 | 'database.vendors.msql', 56 | 'database.vendors.ovrimos', 57 | 'database.vendors.paradox', 58 | 'fileprocess.file.dio', 59 | 'fileprocess.file.inotify', 60 | 'fileprocess.file.xattr', 61 | 'fileprocess.file.xdiff', 62 | 'fileprocess.process.expect', 63 | 'fileprocess.process.libevent', 64 | 'international.fribidi', 65 | 'remote.auth.kadm5', 66 | 'remote.auth.radius', 67 | 'remote.mail.cyrus', 68 | 'remote.mail.mailparse', 69 | 'remote.mail.vpopmail', 70 | 'remote.other.chdb', 71 | 'remote.other.fam', 72 | 'remote.other.gearman', 73 | 'remote.other.gupnp', 74 | 'remote.other.hw', 75 | 'remote.other.hwapi', 76 | 'remote.other.java', 77 | 'remote.other.mqseries', 78 | 'remote.other.net-gopher', 79 | 'remote.other.nis', 80 | 'remote.other.notes', 81 | 'remote.other.ssh2', 82 | 'remote.other.stomp', 83 | 'remote.other.svn', 84 | 'remote.other.tcpwrap', 85 | 'remote.other.yaz', 86 | 'search.mnogosearch', 87 | 'search.solr', 88 | 'utilspec.audio.id3', 89 | 'utilspec.audio.openal', 90 | 'utilspec.cmdline.ncurses', 91 | 'utilspec.cmdline.newt', 92 | 'utilspec.image.cairo', 93 | 'utilspec.nontext.fdf', 94 | 'utilspec.nontext.gnupg', 95 | 'utilspec.nontext.ming', 96 | 'utilspec.nontext.pdf', 97 | 'utilspec.nontext.ps', 98 | 'utilspec.nontext.rpmreader', 99 | 'utilspec.nontext.swf', 100 | 'utilspec.windows.printer', 101 | 'utilspec.windows.w32api', 102 | 'utilspec.windows.win32ps', 103 | 'utilspec.windows.win32service', 104 | 'webservice.oauth', 105 | 'xml.qtdom', 106 | ); 107 | 108 | /** 109 | * List of new->old sections, to ease with transition 110 | */ 111 | $sectionEquivalents = array( 112 | 'basic.other.misc' => 'basic_functions', 113 | 'basic.other.spl' => 'php_spl', 114 | 'basic.other.stream' => 'streamsfuncs', 115 | 'basic.php.outcontrol' => 'output', 116 | 'basic.text.pcre' => 'php_pcre', 117 | 'basic.text.regex' => 'ereg', 118 | 'basic.text.strings' => 'string', 119 | 'compression.bzip2' => 'bz2', 120 | 'compression.zip' => 'php_zip', 121 | 'database.abstract.uodbc' => 'php_odbc', 122 | 'database.vendors.ibase' => 'interbase', 123 | 'database.vendors.mssql' => 'php_mssql', 124 | 'fileprocess.file.filesystem' => 'file', 125 | 'math.bc' => 'bcmath', 126 | 'remote.mail.imap' => 'php_imap', 127 | 'remote.other.ftp' => 'php_ftp', 128 | 'utilspec.server.apache' => 'php_apache', 129 | 'xml.dom' => 'php_dom', 130 | ); 131 | 132 | define('PHP_DOC_DIR', __DIR__ . '/.phpdoc'); 133 | 134 | if (!is_dir(PHP_DOC_DIR)) { 135 | mkdir(PHP_DOC_DIR); 136 | } 137 | 138 | chdir(PHP_DOC_DIR); 139 | 140 | if (!is_dir('doc-base')) { 141 | runCmd('svn checkout http://svn.php.net/repository/phpdoc/doc-base/trunk ./doc-base'); 142 | } 143 | 144 | if (!is_dir('phd')) { 145 | runCmd('git clone https://github.com/php/phd.git ./phd'); 146 | } 147 | 148 | chdir('..'); 149 | 150 | // We have to generate English no matter what 151 | genDocsForLang('en'); 152 | 153 | if ($lang !== 'en') { 154 | genDocsForLang($lang); 155 | } 156 | 157 | function genDocsForLang($lang) { 158 | chdir(PHP_DOC_DIR); 159 | 160 | if (!is_dir($lang)) { 161 | runCmd("svn checkout http://svn.php.net/repository/phpdoc/{$lang}/trunk ./{$lang}"); 162 | } 163 | 164 | if (!is_file("doc-base/.manual.{$lang}.xml")) { 165 | chdir('doc-base'); 166 | runCmd("php configure.php --with-lang={$lang} --output=.manual.{$lang}.xml"); 167 | chdir('..'); 168 | } 169 | 170 | if (!is_dir("phd/output-{$lang}")) { 171 | chdir('phd'); 172 | runCmd("php render.php -d ../doc-base/.manual.{$lang}.xml --package IDE --format json --output ./output-{$lang}/"); 173 | chdir('..'); 174 | } 175 | 176 | chdir('..'); 177 | } 178 | 179 | function printUsage($error = false) { 180 | echo ($error ? "Error: {$error}\n" : '') . "Usage: php generate.php \n"; 181 | exit(1); 182 | } 183 | 184 | function runCmd() { 185 | $args = func_get_args(); 186 | 187 | if (isset($args[0]) && false === $args[0]) { 188 | array_shift($args); 189 | $cmd = array_shift($args); 190 | } else { 191 | $cmd = false; 192 | } 193 | 194 | if (false !== $cmd) { 195 | array_unshift($args, $cmd); 196 | } 197 | 198 | $cmd = implode(' ', $args); 199 | echo "Running: {$cmd}\n"; 200 | exec($cmd, $output, $ret); 201 | 202 | if (0 !== $ret) { 203 | echo "Command failed. Aborting.\n"; 204 | echo "Output:\n"; 205 | echo implode("\n", $output); 206 | exit(1); 207 | } 208 | 209 | echo "Done.\n"; 210 | } 211 | 212 | $phdOutputDir = realpath(PHP_DOC_DIR . "/phd/output-{$lang}"); 213 | $outputDir = realpath(dirname(dirname(__DIR__))); 214 | 215 | $phdOutputDir = realpath($phdOutputDir); 216 | $phdIndex = "{$phdOutputDir}/index.sqlite"; 217 | $phdJsonOutputDir = "{$phdOutputDir}/ide-json"; 218 | 219 | if (empty($phdOutputDir) || !is_dir($phdOutputDir)) { 220 | throw new Exception('Cannot find phd output directory!'); 221 | } else if (!is_dir($phdJsonOutputDir)) { 222 | throw new Exception('Missing JSON data in phd output directory!'); 223 | } else if (!file_exists($phdIndex)) { 224 | throw new Exception('Missing phd SQLite index!'); 225 | } 226 | 227 | $db = new SQLite3($phdIndex); 228 | 229 | $result = $db->query('SELECT docbook_id, parent_id FROM ids'); 230 | 231 | $parentIds = array(); 232 | 233 | while ($row = $result->fetchArray(SQLITE3_ASSOC)) { 234 | $parentIds[$row['docbook_id']] = $row['parent_id']; 235 | } 236 | 237 | function getSectionName($id, $raw = false) { 238 | global $parentIds, $sectionEquivalents; 239 | 240 | $orig = $id; 241 | $suffix = ''; 242 | 243 | while (isset($parentIds[$id]) && $parentId = $parentIds[$id]) { 244 | $id = $parentId; 245 | 246 | if ('book.' === substr($parentId, 0, 5)) { 247 | $suffix = '.' . substr($parentId, 5); 248 | } else if ('refs.' === substr($parentId, 0, 5)) { 249 | $sect = substr($parentId, 5) . $suffix; 250 | 251 | if ($raw) { 252 | return $sect; 253 | } 254 | 255 | if (array_key_exists($sect, $sectionEquivalents)) { 256 | return $sectionEquivalents[$sect]; 257 | } 258 | 259 | $sect = explode('.', $sect); 260 | 261 | return array_pop($sect); 262 | } 263 | } 264 | 265 | die("Could not determine section name for {$orig}"); 266 | } 267 | 268 | function parseInfo($info) { 269 | $params = array(); 270 | 271 | foreach ($info->params as $param) { 272 | $param->name = trim($param->name); 273 | 274 | $str = $param->type; 275 | $str .= ('...' !== $param->name && '$' !== substr($param->name, 0, 1) ? ' $' : ' ') . $param->name; 276 | 277 | $param->optional = is_bool($param->optional) ? !!$param->optional : ('true' === $param->optional); 278 | 279 | if ($param->optional) { 280 | if (isset($param->initializer)) { 281 | $str .= ' = ' . (!empty($param->initializer) ? $param->initializer : "''"); 282 | } 283 | 284 | $str = "[{$str}]"; 285 | } 286 | 287 | $params[] = $str; 288 | } 289 | 290 | $info->pArgs = $params; 291 | 292 | foreach ($info->pArgs as $argNum => &$arg) { 293 | $arg = str_replace('\\', '\\\\', $arg); 294 | $arg = addslashes(trim($arg)); 295 | $arg = str_replace('$', '\\\\\$', $arg); 296 | $arg = '${' . ($argNum + 1) . ':' . $arg . '}'; 297 | } 298 | 299 | $info->pArgs = implode(', ', $info->pArgs); 300 | 301 | $params = implode(', ', $params); 302 | 303 | if ($info->constructor) { 304 | $returnType = 'object'; 305 | } else { 306 | $returnType = (empty($info->return->type) ? 'void' : $info->return->type); 307 | } 308 | 309 | $info->prototype = "{$returnType} {$info->name}({$params})"; 310 | return $info; 311 | } 312 | 313 | $dir = new DirectoryIterator($phdJsonOutputDir); 314 | 315 | $sections = array(); 316 | $functionsTxtLines = array(); 317 | $functionsPlistLines = array(); 318 | 319 | // phd's IDE-JSON docs don't include these classes and functions, so we add them manually 320 | // Note: this shortcut doesn't support functions with multiple arguments, so if you need to 321 | // add functions with multiple arguments, that functionality will need to be written 322 | $extraFunctions = array( 323 | 'include%bool include(string $path)%Includes and evaluates the specified file', 324 | 'include_once%bool include_once(string $path)%Includes and evaluates the specified file', 325 | 'require%bool require(string $path)%Includes and evaluates the specified file, erroring if the file cannot be included', 326 | 'require_once%bool require_once(string $path)%Includes and evaluates the specified file, erroring if the file cannot be included', 327 | ); 328 | 329 | $classes = array( 330 | 'stdClass', 331 | 'Traversable', 332 | 'IteratorAggregate', 333 | 'Iterator', 334 | 'ArrayAccess', 335 | 'Serializable', 336 | 'RecursiveIterator', 337 | 'OuterIterator', 338 | 'Countable', 339 | 'SeekableIterator', 340 | 'SplObserver', 341 | 'SplSubject', 342 | 'Reflector', 343 | ); 344 | 345 | $exceptionClasses = array( 346 | 'ErrorException', 347 | 'Exception', 348 | 'LogicException', 349 | 'BadFunctionCallException', 350 | 'BadMethodCallException', 351 | 'DomainException', 352 | 'InvalidArgumentException', 353 | 'LengthException', 354 | 'OutOfRangeException', 355 | 'RuntimeException', 356 | 'OutOfBoundsException', 357 | 'OverflowException', 358 | 'RangeException', 359 | 'UnderflowException', 360 | 'UnexpectedValueException', 361 | ); 362 | 363 | foreach ($exceptionClasses as $name) { 364 | $classes[] = $name; 365 | $extraFunctions[] = implode('%', array( 366 | $name, 367 | 'object ' . $name . '([string $message = ""], [int $code = 0], [Exception $previous = NULL])', 368 | "Create a new {$name}", 369 | )); 370 | } 371 | 372 | foreach ($extraFunctions as $line) { 373 | list($name, $prototype, $description) = explode('%', $line); 374 | $functionsTxtLines[$name] = $line; 375 | 376 | if (preg_match('/.*?\((.*?)\)/', $prototype, $matches)) { 377 | $arg = str_replace('$', '\\\\\$', $matches[1]); 378 | $arg = "\${1:{$arg}}"; 379 | $functionsPlistLines[$name] = "\t{display = '{$name}'; insert = '({$arg})';}"; 380 | } 381 | } 382 | 383 | foreach ($dir as $fileinfo) { 384 | if ($fileinfo->isDot() || !preg_match('/\.json$/', $fileinfo->getBasename())) { 385 | continue; 386 | } 387 | 388 | $info = json_decode(file_get_contents($fileinfo->getRealPath())); 389 | 390 | $section = getSectionName($info->manualid, true); 391 | 392 | if (!$section) { 393 | echo "Missing section: {$info->name} -- {$info->manualid}"; 394 | } else if (in_array($section, $excludeSections)) { 395 | // echo "Skipping: {$section} -- {$info->name} -- {$info->manualid}\n"; 396 | continue; 397 | } 398 | 399 | if (false !== strpos($info->name, '.')) { 400 | $parts = array_map('trim', array_filter(explode('.', $info->name))); 401 | $classes[] = $parts[0]; 402 | 403 | if ($parts[1] !== '__construct') { 404 | // echo "Skipping non-constructor {$info->name}\n"; 405 | continue; 406 | } 407 | 408 | $info->name = $parts[0]; 409 | $info->constructor = true; 410 | } else { 411 | $info->constructor = false; 412 | } 413 | 414 | if (!preg_match('/(^function\.)|((\.|--|__)construct$)/', $info->manualid)) { 415 | // Only allow if it's a function like mysqli_prepare that's both procedural 416 | // and object-oriented, which is currently best detected by whether or not its 417 | // name starts with an uppercase letter or not 418 | if (preg_match('/^[A-Z]/', $info->name)) { 419 | // echo "Skipping non-constructor (no procedural equivalent to document): {$info->name}\n"; 420 | continue; 421 | } 422 | } 423 | 424 | $section = getSectionName($info->manualid); 425 | $info = parseInfo($info); 426 | 427 | $data = array( 428 | 'name' => $info->name, 429 | 'prototype' => $info->prototype, 430 | 'description' => str_replace(array("\n", "\r"), " ", $info->purpose), 431 | ); 432 | 433 | // echo "{$section} -- {$info->name} -- {$info->manualid}\n"; 434 | 435 | if (!$info->constructor) { 436 | $sections[$section][] = $info->name; 437 | } 438 | 439 | $functionsTxtLines[$info->name] = implode('%', $data); 440 | $functionsPlistLines[$info->name] = "\t{display = '{$info->name}'; insert = '({$info->pArgs})';}"; 441 | } 442 | 443 | $classes = array_unique($classes); 444 | sort($classes); 445 | asort($functionsTxtLines); 446 | sort($functionsPlistLines); 447 | ksort($sections); 448 | 449 | // echo implode("\n", array_keys($sections)) . "\n"; 450 | // die(); 451 | 452 | $completions = array_unique(array_merge($classes, array_keys($functionsTxtLines))); 453 | sort($completions); 454 | 455 | function getCompletionsXml($completions) { 456 | $compStr = ' '; 457 | $compStr .= implode("\n ", $completions); 458 | $compStr .= ''; 459 | 460 | $str =<< 462 | 463 | 464 | 465 | name 466 | Completions 467 | scope 468 | source.php 469 | settings 470 | 471 | completions 472 | 473 | {$compStr} 474 | 475 | 476 | uuid 477 | 2543E52B-D5CF-4BBE-B792-51F1574EA05F 478 | 479 | 480 | 481 | XML; 482 | 483 | return $str; 484 | } 485 | 486 | $supportDir = "{$outputDir}/Support"; 487 | 488 | file_put_contents("{$supportDir}/function-docs/{$lang}.txt", implode("\n", $functionsTxtLines) . "\n"); 489 | 490 | // Only write the language-agnostic files if we're working with English, otherwise 491 | // we run the risk of getting outdated lists (translations aren't always up-to-date) 492 | if ('en' === $lang) { 493 | file_put_contents("{$supportDir}/functions.json", json_encode(compact('classes', 'sections'))); 494 | file_put_contents("{$supportDir}/functions.plist", 495 | "(\n" . implode(",\n", $functionsPlistLines) . "\n)\n" 496 | ); 497 | file_put_contents("{$outputDir}/Preferences/Completions.tmPreferences", getCompletionsXml($completions)); 498 | 499 | runCmd(__DIR__ . '/generate.rb', "{$supportDir}/functions.json"); 500 | unlink("{$supportDir}/functions.json"); 501 | } 502 | -------------------------------------------------------------------------------- /Support/generate/generate.rb: -------------------------------------------------------------------------------- 1 | #!/usr/local/opt/ruby187/bin/ruby -wKU 2 | 3 | # Generate grammar selectors from the PHP docs JSON file produced by generate.php 4 | # 5 | # Note: this file is ran automatically by generate.php - you should not need to run 6 | # it manually. 7 | # 8 | # Usage: generate.rb jsonFile 9 | 10 | require 'rubygems' 11 | require 'json' 12 | require '~/Library/Application Support/TextMate/Bundles/php.tmbundle/Support/lib/Builder' 13 | require '~/Library/Application Support/TextMate/Bundles/bundle-support.tmbundle/Support/shared/lib/osx/plist' 14 | 15 | data = JSON.parse(File.read(ARGV[0])) 16 | 17 | # Escape strings before passing though to regex building 18 | 19 | classes = data['classes'].map! { |name| Regexp.escape(name) } 20 | 21 | sections = { } 22 | data['sections'].each { |section, values| 23 | sections[section] = values.map! { |name| Regexp.escape(name) } 24 | } 25 | 26 | # ================== 27 | # = Syntax writing = 28 | # ================== 29 | # process_list 30 | # Created by Allan Odgaard on 2005-11-28. 31 | # http://macromates.com/svn/Bundles/trunk/Bundles/Objective-C.tmbundle/Support/list_to_regexp.rb 32 | # 33 | # Read list and output a compact regexp 34 | # which will match any of the elements in the list 35 | # Modified by Ciarån Walsh to accept a plain string array 36 | def process_list(list) 37 | buckets = { } 38 | optional = false 39 | 40 | list.map! { |term| term.unpack('C*') } 41 | 42 | list.each do |str| 43 | if str.empty? then 44 | optional = true 45 | else 46 | ch = str.shift 47 | buckets[ch] = (buckets[ch] or []).push(str) 48 | end 49 | end 50 | 51 | unless buckets.empty? then 52 | ptrns = buckets.collect do |key, value| 53 | [key].pack('C') + process_list(value.map{|item| item.pack('C*') }).to_s 54 | end 55 | 56 | if optional == true then 57 | "(" + ptrns.join("|") + ")?" 58 | elsif ptrns.length > 1 then 59 | "(" + ptrns.join("|") + ")" 60 | else 61 | ptrns 62 | end 63 | end 64 | end 65 | 66 | def pattern_for(name, list) 67 | return unless list = process_list(list) 68 | { 69 | 'name' => name, 70 | 'match' => "(?i)\\b#{ list }\\b" 71 | } 72 | end 73 | 74 | def pattern_for_classes(name, list) 75 | return unless list = process_list(list) 76 | { 77 | 'name' => name, 78 | 'match' => "(?i)(\\\\)?\\b#{ list }\\b", 79 | 'captures' => { '1' => {'name' => 'punctuation.separator.inheritance.php'} } 80 | } 81 | end 82 | 83 | GrammarPath = File.dirname(__FILE__) + '/../../Syntaxes/PHP.plist' 84 | 85 | grammar = OSX::PropertyList.load(File.read(GrammarPath)) 86 | 87 | patterns = [] 88 | 89 | sections.sort.each do |(section, funcs)| 90 | patterns << pattern_for('support.function.' + section + '.php', funcs) 91 | end 92 | patterns << pattern_for('support.function.alias.php', %w{is_int is_integer}) 93 | 94 | class_patterns = [pattern_for_classes('support.class.builtin.php', classes)] 95 | 96 | grammar['repository']['support'] = { 'patterns' => patterns } 97 | grammar['repository']['class-builtin'] = { 'patterns' => class_patterns } 98 | 99 | File.open(GrammarPath, 'w') do |file| 100 | file << grammar.to_plist 101 | end 102 | -------------------------------------------------------------------------------- /Support/help.markdown: -------------------------------------------------------------------------------- 1 | # Language 2 | 3 | **Note**: you should always select the `HTML` language when working with PHP (and not the `PHP` language). You can switch language by selecting `HTML` from the status bar at the bottom of the window, or by pressing `⌃⌥⇧H`. 4 | 5 | # Snippets 6 | 7 | ## Control Structures 8 | 9 | The PHP bundle includes snippets for the common control structures, such as `if`, `while`, `switch` and `for`, as well as `function` and `class` definitions. 10 | These snippets are accessible through a tab trigger for the relevant keyword. 11 | Some snippets are also available in the HTML scope for use in templating using PHP; these will be wrapped in `` blocks (See the Short Tags section below for details on how to use short tags instead). 12 | 13 | These snippets are designed to conform to the [PEAR style guide][]. To summarise: 14 | 15 | * Control structures have a space between the keyword and opening parenthesis and have their opening brace on the same line. 16 | * Functions should be called with no spaces between the function name, the opening parenthesis, and the first parameter. 17 | * Function and class definitions have their brace on the line following the prototype. 18 | 19 | [PEAR style guide]: http://pear.php.net/manual/en/standards.php 20 | 21 | ## PHPDoc 22 | 23 | There are several snippets available for use when writing PHPDoc blocks. See the separate Help command for more information. 24 | 25 | # Commands 26 | 27 | ## Completion 28 | 29 | Standard completion for built-in function names is provided by pressing the ⎋ key. 30 | Additionally, completing a built-in function using ⌥⎋ will display a list of available options, and will expand the chosen option into a snippet for the function prototype. 31 | When ⎋ completion is invoked inside of a string following an `include`/`require`, the filename will be completed instead. The environment variable `PHP_INCLUDE_PATH` is used to look for matching files - see "Include Path Configuration" below for details on this. 32 | 33 | ## Function Reference 34 | 35 | There are 2 help commands, both of which work on the current word: 36 | 37 | * Pressing ⌃H will open a browser showing the function definition on the PHP website (or a local file, see `PHP Manual Location` below). 38 | * Pressing ⌥F1 will display a tooltip showing the function prototype and a brief description of its use. 39 | 40 | ## Drag Commands 41 | 42 | Dragging a .php file (from the Project Drawer or Finder, for example) into PHP source will generate an `include` for that file. 43 | If the environment variable `PHP_INCLUDE_PATH` is set to your PHP environment's `include_path` directive, it will be searched for the optimal path to the dropped file to include. 44 | You can hold ⌃ when you drop the file to generate a `require` instead, and you can hold ⌥ to use the `_once` variant of either method. 45 | 46 | ## Project Navigation 47 | 48 | The command ⇧⌘D can be used to jump to a file included from the current document. If invoked on a line with an `include`/`require` directive, it will search for that file. Otherwise, a menu of all the included files will be displayed. The environment variable `PHP_INCLUDE_PATH` is searched for the included path as above. 49 | 50 | # Setup 51 | 52 | ## PHP Versions 53 | 54 | If you use PHP 5 (rather than PHP 4 which is bundled with OS X) then you’ll want to make sure TextMate is using PHP 5 so that the Validate and Run commands work. To do this you’ll need to have PHP 5 installed – I recommend [these packages](http://www.entropy.ch/software/macosx/php/). 55 | 56 | Once PHP is installed, you need to make TextMate use the new PHP binary. You can either replace the default `/usr/bin/php` with the PHP 5 binary (e.g. with a symlink) or you can set the `TM_PHP` environment variable to the absolute path to the PHP executable through TextMate → Preferences → Advanced → Shell Variables. 57 | 58 | ## Include Path Configuration 59 | 60 | The environment variable `PHP_INCLUDE_PATH` is used for the 2 commands above. This variable should contain a colon-separated list of directories to scan for PHP include files (as in your PHP configuration). The correct value for this variable can be found either by checking the output of phpInfo() or printing the result of get\_include_path(). The best way to set this up is as a [Project Dependent Variable](?project_dependent_variables) – make sure nothing is selected in the project drawer and then press the ⓘ icon to configure these. 61 | 62 | See section 9, "Environment variables" in the [TextMate help](?environment_variables) for more information on setting environment variables. 63 | 64 | ## PHP Manual Location 65 | 66 | If you don't have a persistent internet connection (or you just want a quicker response), you can store a local copy of the PHP manual for documentation lookups. You need to download and extract a copy of the “Many HTML files” manual package in your language from [the PHP website](http://www.php.net/download-docs.php). Then set an environment variable `PHP_MANUAL_LOCATION` to the full path of the extracted files, and your local copy will be used instead of routing to the PHP website. 67 | 68 | ## TextMate Support File 69 | 70 | The bundle contains a file with support code that you can include in your project by using the snippet `tmphp⇥`. This file currently contains 2 things: 71 | 72 | * A function `textmate_backtrace`() which works just like `debug_print_backtrace`() but will add a link to jump to files in TextMate 73 | * JavaScript code which will scan the page for PHP errors and add links to open the relevant file and line in TextMate 74 | 75 | There are 3 ways to include this JavaScript: 76 | 1. If `TEXMATE_ERRORS` is define()d before the support file is included then the script tags will automatically be printed at the end of the page. This has the disadvantage that it will invalidate the page source. 77 | 2. You can call `textmate_print_error_handler`() anywhere in your code to print the JavaScript. 78 | 3. Alternatively, you can use the `phperr⇥` snippet in HTML to insert the script tags directly into your template. 79 | 80 | ## Short Tags 81 | 82 | If you want the various snippets to use short tags, i.e. `` rather than ``, then you can set a shell variable in Preferences (under Advanced): 83 | 84 | * Set `TM_PHP_OPEN_TAG` to an empty value to use short-tags. 85 | * Set `TM_PHP_OPEN_TAG_WITH_ECHO` to either `" echo"` (without the quotes) to use short tags, or to `=` to use the short-form for echo statements. 86 | 87 | 88 | ## Miscellaneous 89 | 90 | You may find it preferable to add ‘`$`’ to the list of word characters recognised by TextMate. To do this, open the TextMate → Preferences… → Text Editing dialog and type a single ‘`$`’ character in the “Word Characters” text field. With this change, moving by a word with ⌥← and ⌥→ will jump over PHP variables instead of stopping at the ‘`$`’ symbol. 91 | -------------------------------------------------------------------------------- /Support/lib/Builder.rb: -------------------------------------------------------------------------------- 1 | # This is a single-file version of Jim Weirich's Builder suite version 1.2.3, 2 | # including some very minor tweaks required to make it work with Ruby 1.6.8. 3 | # Copyright 2004 by Jim Weirich (jim@weirichhouse.org). 4 | # All rights reserved. 5 | # 6 | # Create XML markup easily. All (well, almost all) methods sent to 7 | # an XmlMarkup object will be translated to the equivalent XML 8 | # markup. Any method with a block will be treated as an XML markup 9 | # tag with nested markup in the block. 10 | # 11 | # Examples will demonstrate this easier than words. In the 12 | # following, +xm+ is an +XmlMarkup+ object. 13 | # 14 | # xm.em("emphasized") # => emphasized 15 | # xm.em { xmm.b("emp & bold") } # => emph & bold 16 | # xm.a("A Link", "href"=>"http://onestepback.org") 17 | # # => A Link 18 | # xm.div { br } # =>

19 | # xm.target("name"=>"compile", "option"=>"fast") 20 | # # => 21 | # # NOTE: order of attributes is not specified. 22 | # 23 | # xm.instruct! # 24 | # xm.html { # 25 | # xm.head { # 26 | # xm.title("History") # History 27 | # } # 28 | # xm.body { # 29 | # xm.comment! "HI" # 30 | # xm.h1("Header") #

Header

31 | # xm.p("paragraph") #

paragraph

32 | # } # 33 | # } # 34 | # 35 | 36 | 37 | # blankslate.rb: 38 | 39 | #!/usr/bin/env ruby 40 | #-- 41 | # Copyright 2004 by Jim Weirich (jim@weirichhouse.org). 42 | # All rights reserved. 43 | 44 | # Permission is granted for use, copying, modification, distribution, 45 | # and distribution of modified versions of this work as long as the 46 | # above copyright notice is included. 47 | #++ 48 | 49 | module Builder 50 | 51 | # BlankSlate provides an abstract base class with no predefined 52 | # methods (except for \_\_send__ and \_\_id__). 53 | # BlankSlate is useful as a base class when writing classes that 54 | # depend upon method_missing (e.g. dynamic proxies). 55 | class BlankSlate 56 | class << self 57 | def hide(name) 58 | undef_method name if 59 | instance_methods.include?(name.to_s) and 60 | name !~ /^(__|instance_eval)/ 61 | end 62 | end 63 | 64 | instance_methods.each { |m| hide(m) } 65 | end 66 | end 67 | 68 | # Since Ruby is very dynamic, methods added to the ancestors of 69 | # BlankSlate after BlankSlate is defined will show up in the 70 | # list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined 71 | module Kernel 72 | class << self 73 | alias_method :blank_slate_method_added, :method_added 74 | def method_added(name) 75 | blank_slate_method_added(name) 76 | return if self != Kernel 77 | Builder::BlankSlate.hide(name) 78 | end 79 | end 80 | end 81 | 82 | class Object 83 | class << self 84 | alias_method :blank_slate_method_added, :method_added 85 | def method_added(name) 86 | blank_slate_method_added(name) 87 | return if self != Object 88 | Builder::BlankSlate.hide(name) 89 | end 90 | end 91 | end 92 | 93 | # xmlbase.rb 94 | module Builder 95 | 96 | # Generic error for builder 97 | class IllegalBlockError < RuntimeError; end 98 | 99 | # XmlBase is a base class for building XML builders. See 100 | # Builder::XmlMarkup and Builder::XmlEvents for examples. 101 | class XmlBase < BlankSlate 102 | 103 | # Create an XML markup builder. 104 | # 105 | # out:: Object receiving the markup.1 +out+ must respond to 106 | # <<. 107 | # indent:: Number of spaces used for indentation (0 implies no 108 | # indentation and no line breaks). 109 | # initial:: Level of initial indentation. 110 | # 111 | def initialize(indent=0, initial=0) 112 | @indent = indent 113 | @level = initial 114 | @self = nil 115 | end 116 | 117 | # Create a tag named +sym+. Other than the first argument which 118 | # is the tag name, the arguements are the same as the tags 119 | # implemented via method_missing. 120 | def tag!(sym, *args, &block) 121 | self.__send__(sym, *args, &block) 122 | end 123 | 124 | # Create XML markup based on the name of the method. This method 125 | # is never invoked directly, but is called for each markup method 126 | # in the markup block. 127 | def method_missing(sym, *args, &block) 128 | text = nil 129 | attrs = nil 130 | sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol) 131 | args.each do |arg| 132 | case arg 133 | when Hash 134 | attrs ||= {} 135 | attrs.update(arg) # was merge!, which ruby 1.6.8 doesn't support 136 | else 137 | text ||= '' 138 | text << arg.to_s 139 | end 140 | end 141 | if block 142 | unless text.nil? 143 | raise ArgumentError, "XmlMarkup cannot mix a text argument with a block" 144 | end 145 | _capture_outer_self(block) if @self.nil? 146 | _indent 147 | _start_tag(sym, attrs) 148 | _newline 149 | _nested_structures(block) 150 | _indent 151 | _end_tag(sym) 152 | _newline 153 | elsif text.nil? 154 | _indent 155 | _start_tag(sym, attrs, true) 156 | _newline 157 | else 158 | _indent 159 | _start_tag(sym, attrs) 160 | text! text 161 | _end_tag(sym) 162 | _newline 163 | end 164 | @target 165 | end 166 | 167 | # Append text to the output target. Escape any markup. May be 168 | # used within the markup brakets as: 169 | # 170 | # builder.p { |b| b.br; b.text! "HI" } #=>


HI

171 | def text!(text) 172 | _text(_escape(text)) 173 | end 174 | 175 | # Append text to the output target without escaping any markup. 176 | # May be used within the markup brakets as: 177 | # 178 | # builder.p { |x| x << "
HI" } #=>


HI

179 | # 180 | # This is useful when using non-builder enabled software that 181 | # generates strings. Just insert the string directly into the 182 | # builder without changing the inserted markup. 183 | # 184 | # It is also useful for stacking builder objects. Builders only 185 | # use << to append to the target, so by supporting this 186 | # method/operation builders can use other builders as their 187 | # targets. 188 | def <<(text) 189 | _text(text) 190 | end 191 | 192 | # For some reason, nil? is sent to the XmlMarkup object. If nil? 193 | # is not defined and method_missing is invoked, some strange kind 194 | # of recursion happens. Since nil? won't ever be an XML tag, it 195 | # is pretty safe to define it here. (Note: this is an example of 196 | # cargo cult programming, 197 | # cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming). 198 | def nil? 199 | false 200 | end 201 | 202 | private 203 | 204 | def _escape(text) 205 | text. 206 | gsub(%r{&}, '&'). 207 | gsub(%r{<}, '<'). 208 | gsub(%r{>}, '>') 209 | end 210 | 211 | def _capture_outer_self(block) 212 | @self = eval("self", block) 213 | end 214 | 215 | def _newline 216 | return if @indent == 0 217 | text! "\n" 218 | end 219 | 220 | def _indent 221 | return if @indent == 0 || @level == 0 222 | text!(" " * (@level * @indent)) 223 | end 224 | 225 | def _nested_structures(block) 226 | @level += 1 227 | block.call(self) 228 | ensure 229 | @level -= 1 230 | end 231 | end 232 | end 233 | 234 | # xmlmarkup.rb 235 | module Builder 236 | 237 | # Create XML markup easily. All (well, almost all) methods sent to 238 | # an XmlMarkup object will be translated to the equivalent XML 239 | # markup. Any method with a block will be treated as an XML markup 240 | # tag with nested markup in the block. 241 | # 242 | # Examples will demonstrate this easier than words. In the 243 | # following, +xm+ is an +XmlMarkup+ object. 244 | # 245 | # xm.em("emphasized") # => emphasized 246 | # xm.em { xmm.b("emp & bold") } # => emph & bold 247 | # xm.a("A Link", "href"=>"http://onestepback.org") 248 | # # => A Link 249 | # xm.div { br } # =>

250 | # xm.target("name"=>"compile", "option"=>"fast") 251 | # # => 252 | # # NOTE: order of attributes is not specified. 253 | # 254 | # xm.instruct! # 255 | # xm.html { # 256 | # xm.head { # 257 | # xm.title("History") # History 258 | # } # 259 | # xm.body { # 260 | # xm.comment! "HI" # 261 | # xm.h1("Header") #

Header

262 | # xm.p("paragraph") #

paragraph

263 | # } # 264 | # } # 265 | # 266 | # == Notes: 267 | # 268 | # * The order that attributes are inserted in markup tags is 269 | # undefined. 270 | # 271 | # * Sometimes you wish to insert text without enclosing tags. Use 272 | # the text! method to accomplish this. 273 | # 274 | # Example: 275 | # 276 | # xm.div { #
277 | # xm.text! "line"; xm.br # line
278 | # xm.text! "another line"; xmbr # another line
279 | # } #
280 | # 281 | # * The special XML characters <, >, and & are converted to <, 282 | # > and & automatically. Use the << operation to 283 | # insert text without modification. 284 | # 285 | # * Sometimes tags use special characters not allowed in ruby 286 | # identifiers. Use the tag! method to handle these 287 | # cases. 288 | # 289 | # Example: 290 | # 291 | # xml.tag!("SOAP:Envelope") { ... } 292 | # 293 | # will produce ... 294 | # 295 | # ... " 296 | # 297 | # tag! will also take text and attribute arguments (after 298 | # the tag name) like normal markup methods. (But see the next 299 | # bullet item for a better way to handle XML namespaces). 300 | # 301 | # * Direct support for XML namespaces is now available. If the 302 | # first argument to a tag call is a symbol, it will be joined to 303 | # the tag to produce a namespace:tag combination. It is easier to 304 | # show this than describe it. 305 | # 306 | # xml.SOAP :Envelope do ... end 307 | # 308 | # Just put a space before the colon in a namespace to produce the 309 | # right form for builder (e.g. "SOAP:Envelope" => 310 | # "xml.SOAP :Envelope") 311 | # 312 | # * XmlMarkup builds the markup in any object (called a _target_) 313 | # that accepts the << method. If no target is given, 314 | # then XmlMarkup defaults to a string target. 315 | # 316 | # Examples: 317 | # 318 | # xm = Builder::XmlMarkup.new 319 | # result = xm.title("yada") 320 | # # result is a string containing the markup. 321 | # 322 | # buffer = "" 323 | # xm = Builder::XmlMarkup.new(buffer) 324 | # # The markup is appended to buffer (using <<) 325 | # 326 | # xm = Builder::XmlMarkup.new(STDOUT) 327 | # # The markup is written to STDOUT (using <<) 328 | # 329 | # xm = Builder::XmlMarkup.new 330 | # x2 = Builder::XmlMarkup.new(:target=>xm) 331 | # # Markup written to +x2+ will be send to +xm+. 332 | # 333 | # * Indentation is enabled by providing the number of spaces to 334 | # indent for each level as a second argument to XmlBuilder.new. 335 | # Initial indentation may be specified using a third parameter. 336 | # 337 | # Example: 338 | # 339 | # xm = Builder.new(:ident=>2) 340 | # # xm will produce nicely formatted and indented XML. 341 | # 342 | # xm = Builder.new(:indent=>2, :margin=>4) 343 | # # xm will produce nicely formatted and indented XML with 2 344 | # # spaces per indent and an over all indentation level of 4. 345 | # 346 | # builder = Builder::XmlMarkup.new(:target=>$stdout, :indent=>2) 347 | # builder.name { |b| b.first("Jim"); b.last("Weirich) } 348 | # # prints: 349 | # # 350 | # # Jim 351 | # # Weirich 352 | # # 353 | # 354 | # * The instance_eval implementation which forces self to refer to 355 | # the message receiver as self is now obsolete. We now use normal 356 | # block calls to execute the markup block. This means that all 357 | # markup methods must now be explicitly send to the xml builder. 358 | # For instance, instead of 359 | # 360 | # xml.div { strong("text") } 361 | # 362 | # you need to write: 363 | # 364 | # xml.div { xml.strong("text") } 365 | # 366 | # Although more verbose, the subtle change in semantics within the 367 | # block was found to be prone to error. To make this change a 368 | # little less cumbersome, the markup block now gets the markup 369 | # object sent as an argument, allowing you to use a shorter alias 370 | # within the block. 371 | # 372 | # For example: 373 | # 374 | # xml_builder = Builder::XmlMarkup.new 375 | # xml_builder.div { |xml| 376 | # xml.stong("text") 377 | # } 378 | # 379 | class XmlMarkup < XmlBase 380 | 381 | # Create an XML markup builder. Parameters are specified by an 382 | # option hash. 383 | # 384 | # :target=>target_object:: 385 | # Object receiving the markup. +out+ must respond to the 386 | # << operator. The default is a plain string target. 387 | # :indent=>indentation:: 388 | # Number of spaces used for indentation. The default is no 389 | # indentation and no line breaks. 390 | # :margin=>initial_indentation_level:: 391 | # Amount of initial indentation (specified in levels, not 392 | # spaces). 393 | # 394 | def initialize(options={}) 395 | indent = options[:indent] || 0 396 | margin = options[:margin] || 0 397 | super(indent, margin) 398 | @target = options[:target] || "" 399 | end 400 | 401 | # Return the target of the builder. 402 | def target! 403 | @target 404 | end 405 | 406 | def comment!(comment_text) 407 | _ensure_no_block block_given? 408 | _special("", comment_text, nil) 409 | end 410 | 411 | # Insert an XML declaration into the XML markup. 412 | # 413 | # For example: 414 | # 415 | # xml.declare! :ELEMENT, :blah, "yada" 416 | # # => 417 | def declare!(inst, *args, &block) 418 | _indent 419 | @target << "" 435 | _newline 436 | end 437 | 438 | # Insert a processing instruction into the XML markup. E.g. 439 | # 440 | # For example: 441 | # 442 | # xml.instruct! 443 | # #=> 444 | # xml.instruct! :aaa, :bbb=>"ccc" 445 | # #=> 446 | # 447 | def instruct!(directive_tag=:xml, attrs={}) 448 | _ensure_no_block block_given? 449 | if directive_tag == :xml 450 | a = { :version=>"1.0", :encoding=>"UTF-8" } 451 | attrs = a.dup.update attrs # was merge, which isn't available with ruby 1.6.8 452 | end 453 | _special( 454 | "", 456 | nil, 457 | attrs, 458 | [:version, :encoding, :standalone]) 459 | end 460 | 461 | private 462 | 463 | # NOTE: All private methods of a builder object are prefixed when 464 | # a "_" character to avoid possible conflict with XML tag names. 465 | 466 | # Insert text directly in to the builder's target. 467 | def _text(text) 468 | @target << text 469 | end 470 | 471 | # Insert special instruction. 472 | def _special(open, close, data=nil, attrs=nil, order=[]) 473 | _indent 474 | @target << open 475 | @target << data if data 476 | _insert_attributes(attrs, order) if attrs 477 | @target << close 478 | _newline 479 | end 480 | 481 | # Start an XML tag. If end_too is true, then the start 482 | # tag is also the end tag (e.g.
483 | def _start_tag(sym, attrs, end_too=false) 484 | @target << "<#{sym}" 485 | _insert_attributes(attrs) 486 | @target << "/" if end_too 487 | @target << ">" 488 | end 489 | 490 | # Insert an ending tag. 491 | def _end_tag(sym) 492 | @target << "" 493 | end 494 | 495 | # Insert the attributes (given in the hash). 496 | def _insert_attributes(attrs, order=[]) 497 | return if attrs.nil? 498 | order.each do |k| 499 | v = attrs[k] 500 | @target << %{ #{k}="#{v}"} if v 501 | end 502 | attrs.each do |k, v| 503 | @target << %{ #{k}="#{v}"} unless order.member?(k) 504 | end 505 | end 506 | 507 | def _ensure_no_block(got_block) 508 | if got_block 509 | fail IllegalBlockError, 510 | "Blocks are not allowed on XML instructions" 511 | end 512 | end 513 | 514 | end 515 | 516 | end 517 | 518 | -------------------------------------------------------------------------------- /Support/lib/php.rb: -------------------------------------------------------------------------------- 1 | class PHPFunction 2 | def initialize(prototype) 3 | @parts = prototype.strip.match(/^\s*(?:([0-9A-Za-z|_]+)\s+)?(\w+)\s*\((.*)\).*$/) 4 | end 5 | 6 | def params 7 | params = @parts[3] rescue '' 8 | 9 | params.scan(/(?:\[\s*)?(\w+ )?(&?\$?[\w.|]+)(?:\s*=\s*(.+))?(\])?,?/).map do |(type, name, default, optional_bracket)| 10 | param = type.to_s + name 11 | optional = false 12 | if optional_bracket 13 | # Optional 14 | param = '[' + param + ']' 15 | optional = true 16 | elsif default 17 | # Optional with default 18 | param = '[' + param + ' = ' + default + ']' 19 | optional = true 20 | end 21 | { 22 | :param => param, 23 | :type => type.to_s.strip, 24 | :name => name.to_s, 25 | :optional => optional, 26 | :default => default 27 | } 28 | end 29 | end 30 | 31 | def name 32 | @parts[2] 33 | end 34 | 35 | def type 36 | @parts[1] 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /Support/lib/php_mate.rb: -------------------------------------------------------------------------------- 1 | require "#{ENV["TM_SUPPORT_PATH"]}/lib/scriptmate" 2 | 3 | class PhpScript < UserScript 4 | def lang; "Php" end 5 | # Disable display_errors so that errors are printed to stderr only 6 | # Enabling log_errors (without an error_log) sends errors to stdout 7 | def default_extension; ".php" end 8 | def args 9 | ['-d display_errors=0', '-d log_errors=1', '-d error_log='] 10 | end 11 | def filter_cmd(cmd) 12 | # PHP doesn't understand - to mean stdin :( 13 | cmd[cmd.size - 1] = '--' if cmd.last == '-' 14 | cmd 15 | end 16 | def executable; @hashbang || ENV['TM_PHP'] || 'php' end 17 | def version_string 18 | path = ENV['PATH'].split(':').find { |e| File.exists? File.join(e, executable) } 19 | php_path = File.join(path.to_s, executable) 20 | res = %x{ #{executable} -v }.split[0..2].join %{ } 21 | res + " (#{php_path})" 22 | end 23 | end 24 | 25 | class PhpMate < ScriptMate 26 | def filter_stderr(str) 27 | # strings from stderr are passed through this method before printing 28 | super(str). 29 | gsub(/(#\d+ )((.+?)\((\d+)\)): /) { 30 | $1 + ' ' + $2 + ': ' 31 | }. 32 | gsub(/in (.+?) on line (\d+)(
$)?/) { 33 | 'in ' + $1 + ' on line ' + $2 + '' + $3.to_s 34 | } 35 | end 36 | 37 | def filter_stdout(str) 38 | # strings from stderr are passed through this method before printing 39 | super(str).gsub(/\[([^\]]+?) line (\d+)\]
$/) { 40 | '[' + $1 + ' line ' + $2 + ']
' 41 | } 42 | end 43 | end 44 | 45 | script = PhpScript.new(STDIN.read) 46 | PhpMate.new(script).emit_html 47 | -------------------------------------------------------------------------------- /Support/textmate.php: -------------------------------------------------------------------------------- 1 | = 5.2.0) then it is checked 17 | * and javascript will be printed only if there has been an error 18 | * 19 | * If TEXTMATE_NO_ERRORS is defined then the javascript will never be printed 20 | */ 21 | 22 | /* 23 | * Print the javascript to parse and link errors 24 | */ 25 | function textmate_print_error_handler() { 26 | @include(dirname(__FILE__) . "/textmate_error_handler.html"); 27 | } 28 | 29 | /* 30 | * If TEXTMATE_ERRORS is defined then this will set up a shutdown function 31 | * to automatically print the javascript error parser at the end of the page 32 | * If error_get_last() is available (PHP 5 >= 5.2.0) then the javascript 33 | * will be printed only if an error has occured (since printing at the end 34 | * of the page will invalidate it) 35 | */ 36 | if (defined('TEXTMATE_ERRORS')) { 37 | register_shutdown_function(create_function('', ' 38 | if (!function_exists("error_get_last") || error_get_last()) 39 | textmate_print_error_handler();' 40 | )); 41 | } 42 | 43 | /* 44 | * textmate_backtrace() 45 | * 46 | * Dumps a backtrace in the same format as debug_print_backtrace(), adding links 47 | * to files & lines using the txmt://open schema 48 | * 49 | * Regexing the output of debug_print_backtrace() would be easier but we can't use 50 | * output buffering in case it's already being used 51 | */ 52 | function textmate_backtrace() { 53 | echo '
';
54 |     foreach (debug_backtrace() as $number => $trace) {
55 |         echo "#{$number}  ";
56 |         if (isset($trace['class'])) echo $trace['class'], '::';
57 |         echo $trace['function'], '(';
58 |         if (isset($trace['args'])) echo implode(', ', $trace['args']);
59 |         echo ') called at [';
60 |         $file = $line = '';
61 |         if (strpos($trace['file'], 'eval') !== false) {
62 |             $matches = array();
63 |             if (preg_match('/^(.+)\((\d+)\) : eval/', $trace['file'], $matches))
64 |                 list($dummy, $file, $line) = $matches;
65 |         } else {
66 |             $file = $trace['file'];
67 |             $line = $trace['line'];
68 |         }
69 |         echo '', $trace['file'], ':', $trace['line'], "]\n";
70 |     }
71 |     echo '
'; 72 | } 73 | ?> -------------------------------------------------------------------------------- /Support/textmate_error_handler.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Tests/indentation.php: -------------------------------------------------------------------------------- 1 | '1', 55 | '#1' => 1, 56 | // # in previous line shoud not make this line be indented 57 | ); 58 | $form['#after_build'] = array('some_string'); 59 | // # in previous line shoud not make this line be indented 60 | 61 | # No indent after comment lines 62 | bar(); 63 | // No indent after comment lines 64 | baz(); 65 | 66 | ?> -------------------------------------------------------------------------------- /Tests/insert-call-to-parent.php: -------------------------------------------------------------------------------- 1 | function (stdClass $foo = invalid, array $blah) use (&$foo, $bar) { 156 | $test = 'test'; 157 | } 158 | ); 159 | 160 | $blah(); 161 | $blah(1, 2, 3); 162 | blah(1, 2, 3); 163 | 164 | $blah = new Foo(); 165 | $blah = new Foo; 166 | $blah = new \blah\Foo(); 167 | $blah = new blah\Foo(); 168 | $blah = new $foo(); 169 | $blah = new $foo; 170 | $blah = new blah\$Foo(); 171 | 172 | Foo::bar(new test()); 173 | Foo::bar(new test); 174 | blah\Foo::bar(new blah\test()); 175 | 176 | // ======================== 177 | // = String interpolation = 178 | // ======================== 179 | '$foo' 180 | '\'' 181 | '\\' 182 | "1\1111" 183 | "1\x111" 184 | "$foo" 185 | "$foo[bar]" // 'bar' is treated as a string automatically by PHP 186 | "{$foo[bar]}" // 'bar' is treated as a *constant* 187 | "$foo[0]" 188 | "$foo[$bar]" 189 | "$foo->bar" 190 | "$foo->bar(" // Should show as access to property ->bar, not as a call to ->bar() 191 | "$foo->$bar" // Should not show as an object property access, but as two separate variables 192 | "{$foo->$bar}" 193 | "{$foo->{$bar}}" 194 | "{$foo->${bar}}" 195 | "{$foo->{$bar . $baz}}" 196 | "{$foo->bar}" 197 | "{$foo->bar[0]->baz}" 198 | "{$foo->bar(12, $foo)}" 199 | "{$foo(12, $foo)}" 200 | 201 | $foo = $foo->{'foo' . 'bar'}; 202 | $foo = $foo->{"foo{$bar}"}; 203 | 204 | $beer = 'Heineken'; 205 | echo "$beer's taste is great"; // works; "'" is an invalid character for variable names 206 | echo "He drank some $beers"; // won't work; 's' is a valid character for variable names but the variable is "$beer" 207 | echo "He drank some ${beer}s"; // works 208 | echo "He drank some {$beer}s"; // works 209 | 210 | // The text "($str[1" should *not* be highlighted as a syntax error. 211 | $str = array("Foo", "Bar"); 212 | echo 'Name: ' . $str[($str[1]) ? 1 : 0]; // Should echo "Name: Bar" 213 | echo "Name: {$str[($str[1]) ? 1 : 0]}"; // Should echo "Name: Bar" 214 | 215 | echo "{\$"; 216 | echo "$foo"; 217 | echo "$_SERVER[foo]"; 218 | echo "{$_SERVER['foo']}"; 219 | echo "{$foo}"; 220 | echo "${foo}"; // 'foo' should be variable.other.php 221 | echo "$foo->${bar}"; // '->' should not be keyword.operator.class.php 222 | echo "This works: " . $arr['foo'][3]; 223 | echo "This works too: {$obj->values[3]->name}"; 224 | echo "This is the value of the var named $name: {${$name}}"; 225 | echo "This is the value of the var named by the return value of getName(): {${getName()}}"; 226 | echo "Blah: {${Foo::bar()}}"; 227 | 228 | $blah = $foo[123]; 229 | $blah = $foo[$bar]; 230 | $blah = $foo[bar()]; 231 | $blah = $foo->bar(123); 232 | $blah = ${'foo'}; 233 | 234 | $blah = $foo[123]; 235 | $blah = $_POST['blah']; 236 | $blah = new $_POST['blah']; 237 | $blah = new $foo; 238 | $blah = new $foo->{$bar}; 239 | $blah = new $foo->{$bar . '123'}; 240 | $blah = new $foo->{${bar()}}; 241 | 242 | $bar = array( 243 | '123' => '321', 244 | ); 245 | $x = 2; 246 | 247 | echo 'foo ' . $bar['1' . $x . '3']; 248 | echo 'foo ' . $bar["1{$x}3"]; 249 | echo "foo {$bar["1{$x}3"]}"; 250 | 251 | // Heredoc 252 | $foo = <<bar} 254 | Stuff goes here 255 | BLAH; 256 | 257 | // Nowdoc (no interpolation should occur here) 258 | $foo = <<<'BLAH' 259 | Blah blah $foo blah {$foo->bar} 260 | Stuff goes here 261 | BLAH; 262 | 263 | namespace foo\bar; 264 | 265 | E_ERROR 266 | E_DEPRECATED 267 | E_NOTICE 268 | E_COMPILE_ERROR 269 | E_PARSE 270 | E_USER_DEPRECATED 271 | __FILE__ 272 | __DIR__ 273 | __NAMESPACE__ 274 | CURRENCY_SYMBOL 275 | \CURRENCY_SYMBOL 276 | foo\CURRENCY_SYMBOL 277 | E_ERROR 278 | \E_ERROR 279 | foo\E_ERROR 280 | 281 | array_map(); 282 | array_map($test, 'foo', MY_CONST); 283 | \array_map(); 284 | blah\array_map(); 285 | namespace\array_map($test, 'foo'); 286 | 287 | // `namespace` should not be highlighted as a namespace component but rather as an operator like 288 | // `self` or `static` 289 | \foo\blah(); 290 | namespace\foo(); 291 | $blah = new foo(); 292 | $blah = new foo\bar(); 293 | $blah = new foo\bar\(); 294 | $blah = new namespace\Foo(); 295 | $blah = new self\Foo(); 296 | $foo->bar(); 297 | 298 | // `self` and `static` should be storage.type.php 299 | self::foo(); 300 | static::foo(); 301 | static::foo(); 302 | parent::foo(); 303 | Blah::foo(); 304 | \foo\Blah::foo(); 305 | 306 | $foo = self::BAR; 307 | $foo = static::BAR; 308 | $foo = self::$bar; 309 | $foo = static::$bar; 310 | 311 | static::${$test} = 'test'; 312 | Blah::${$test} = 'test'; 313 | \foo\Blah::${$test} = 'test'; 314 | ${$test} = 'test'; 315 | 316 | new self(); // `self` should highlight differently 317 | new static(); // `static` should highlight differently 318 | new Blah(); 319 | 320 | goto foo; 321 | 322 | foo: 323 | 324 | goto blah; 325 | 326 | blah: { 327 | 328 | } 329 | 330 | 331 | // ======= 332 | // = SQL = 333 | // ======= 334 | 335 | // This looks like a mess, but there are quite a few ways you can trick the grammar here, and the 336 | // following lines know all the tricks. 337 | 338 | 'SELECT * from foo WHERE bar = \'foo \\ ' . $foo . ' AND blah'; 339 | 'SELECT * from foo WHERE bar = \'foo \\ ' . $foo . " AND blah"; 340 | 'SELECT * from foo WHERE bar = "foo" asdas' . $foo . '" asdasd'; 341 | 342 | "SELECT \"$foo\" FROM bar"; 343 | "SELECT `$foo` FROM bar"; 344 | "SELECT '$foo' FROM bar"; 345 | 'SELECT \'$foo\' FROM bar'; 346 | 'SELECT `$foo` FROM bar'; 347 | 'SELECT "$foo" FROM bar'; 348 | "SELECT * from foo WHERE bar = 'asd $foo $foo->bar {$foo->bar[12]} asda' 'unclosed string"; 349 | "SELECT * from foo WHERE bar = \"dsa$foo\" \"unclosed string"; 350 | 'SELECT * from foo WHERE bar = "unclosed string'; 351 | 352 | 'SELECT * from foo WHERE bar = ' . $foo . ' bar" AND foo = 1'; 353 | 'SELECT * from foo WHERE bar = ' . ' bar" AND foo = 1'; 354 | 355 | 'SELECT * from foo WHERE bar = "foo \" ' . $foo . ' bar" AND foo = 1'; 356 | 357 | 'SELECT * FROM `foo' . $bar . '` WHERE foo = 1' . fasdf('asdf') . ' AND other = "blah"'; 358 | "SELECT * FROM `foo" . $bar . "` WHERE foo = 1"; 359 | "SELECT * FROM `foo` WHERE foo = 'blah" . $x . "' AND other = 'stuff'"; 360 | "SELECT * FROM `foo` WHERE foo = '{$xblah}" . "' AND other = 'stuff'"; 361 | // Something 362 | 363 | 'SELECT * FROM \` blah'; 364 | "SELECT * FROM `foo` WHERE foo = \"blah" . $x . "\" AND other = 'stuff'"; 365 | 'SELECT * FROM `foo` WHERE foo = "blah' . '" AND other = "stuff"'; 366 | 'SELECT * FROM `foo` WHERE foo = "blah' . $x . '" AND other = "stuff"'; 367 | "SELECT * FROM \``foo" . $bar . "` WHERE foo = 'blah'"; 368 | "SELECT * FROM \"foo" . $bar . "baz\" WHERE foo = 'blah'"; 369 | "SELECT * FROM `foo" . $bar . "baz` WHERE foo = 'blah'"; 370 | "SELECT * FROM 'foo" . $bar . "baz' WHERE foo = 'blah'"; 371 | 'SELECT * FROM \'foo' . $bar . 'baz\' WHERE foo = "blah"'; 372 | 'SELECT * FROM `foo' . $bar . 'baz` WHERE foo = "blah"'; 373 | 'SELECT * FROM "foo' . $bar . 'baz" WHERE foo = "blah"'; 374 | 'SELECT * FROM "foo' . ($bar) . 'baz" WHERE foo = "blah"'; 375 | ('SELECT * FROM "foo') . ($bar) . 'baz" WHERE foo = "blah"'; 376 | 'SELECT * FROM foo' . $bar + 1 . 'baz WHERE foo = "blah"'); 377 | 'SELECT * FROM foo WHERE blah = "blah"'; 378 | 'SELECT * FROM `foo` WHERE blah = "blah"'; 379 | 'SELECT * FROM `f\`' . 'oo` WHERE blah = "blah"'; 380 | 'SELECT * FROM `f\` asd`f \` asdf`' . 'oo` WHERE blah = "blah"'; 381 | 'SELECT * FROM `foo` WHERE blah = "bl\"' . 'ah"'; 382 | "SELECT * FROM foo WHERE blah = 'blah'"; 383 | "SELECT * FROM foo WHERE blah = 'bl\'" . "ah'"; 384 | "SELECT * FROM `foo` WHERE blah = 'blah'"; 385 | "SELECT * FROM `f\`" . "oo` WHERE blah = 'blah'"; 386 | // Comments 387 | 388 | 'SELECT * FROM # foo bar \' asdassdsaas'; 389 | 'SELECT * FROM -- foo bar \' asdassdsaas'; 390 | "SELECT * FROM # foo bar \" asdassdsaas"; 391 | "SELECT * FROM -- foo bar \" asdassdsaas"; 392 | 393 | 394 | $foo = new Bar(); 395 | 396 | $mode = PDO::FETCH_ASSOC; 397 | $mode = \PDO::FETCH_ASSOC; 398 | $mode = namespace\PDO::FETCH_ASSOC; 399 | $blah = \stuff\PDO::FETCH_ASSOC; 400 | $more = stuff\PDO::FETCH_ASSOC; 401 | $blah = \stuff\more\PDO::FETCH_ASSOC; 402 | $more = stuff\more\PDO::FETCH_ASSOC; 403 | $blah = $blah::FETCH_ASSOC; 404 | $blah = \blah\$blah::FETCH_ASSOC; 405 | $blah = \blah\$blah\foo\$blah::FETCH_ASSOC; 406 | 407 | $mode = PDO::$prop; 408 | $mode = \PDO::$prop; 409 | $mode = namespace\PDO::$prop; 410 | $blah = \stuff\PDO::$prop; 411 | $more = stuff\PDO::$prop; 412 | $blah = \stuff\more\PDO::$prop; 413 | $more = stuff\more\PDO::$prop; 414 | 415 | $mode = PDO::staticMethod(); 416 | $mode = \PDO::staticMethod(); 417 | $mode = namespace\PDO::staticMethod(); 418 | $blah = \stuff\PDO::staticMethod(); 419 | $more = stuff\PDO::staticMethod(); 420 | $blah = \stuff\more\PDO::staticMethod(); 421 | $more = stuff\more\PDO::staticMethod(); 422 | $blah = $foo::staticMethod(); 423 | $blah = ($foo::staticMethod()); 424 | $blah = ( $foo::staticMethod()); 425 | 426 | $mode = funcCall(); 427 | $mode = \funcCall(); 428 | $mode = namespace\funcCall(); 429 | $blah = \stuff\funcCall(); 430 | $more = stuff\funcCall(); 431 | $blah = \stuff\more\funcCall(); 432 | $more = stuff\more\funcCall(); 433 | 434 | $blah = $foo->test; 435 | $blah = foo->test; 436 | $blah = ${'foo'}->test; 437 | 438 | // When type hinting: 439 | class Test { 440 | public function __construct(\My\Namespace\MyClass $myClass) { 441 | // .. 442 | } 443 | } 444 | class Test { 445 | public function __construct(namespace\MyClass $myClass) { 446 | // .. 447 | } 448 | } 449 | 450 | // Assuming this is in the same area as type hinting, in catch blocks: 451 | 452 | try { 453 | // .. 454 | } catch (PDOException $e) { 455 | // .. 456 | } 457 | try { 458 | // .. 459 | } catch (asdf\PDOException $e) { 460 | // .. 461 | } 462 | try { 463 | // .. 464 | } catch (\asdf\foo\PDOException $e) { 465 | // .. 466 | } 467 | try { 468 | // .. 469 | } catch (namespace\PDOException $e) { 470 | // .. 471 | } 472 | 473 | // Also while technically not an issue, the namespace keyword isn't actually interpreted as a library keyword and rather as if it was a user defined namespace. (http://www.php.net/manual/en/language.namespaces.nsconstants.php) 474 | 475 | $keyword = new \MyClass(); 476 | $keyword = new namesace\MyClass(); 477 | $blah = new namespace\MyClass(); 478 | $blah = new \namespace\MyClass(); 479 | $blah = new foo\namespace\MyClass(); 480 | 481 | $blah = new blah(); 482 | $blah = new blah\blah(); 483 | $blah = new blah\$blah\$blah\blah(); 484 | 485 | if ($test == 1) { 486 | 487 | } else if (123 === $foo) { 488 | 489 | } elseif (CONST) { 490 | 491 | } else { 492 | 493 | } 494 | 495 | if ($blah instanceof MyClass) { 496 | 497 | } 498 | 499 | if ($blah instanceof foo\MyClass) { 500 | 501 | } 502 | 503 | if ($blah instanceof namespace\foo\MyClass) { 504 | 505 | } 506 | 507 | if ($blah instanceof $b) { 508 | 509 | } 510 | 511 | foo(&$blah); // Ampersand should be invalid.deprecated.call-time-pass-by-reference.php 512 | foo(&$blah, array(), &$blah); // Ampersand should be invalid.deprecated.call-time-pass-by-reference.php 513 | foo(array($blah, &$foo)); // Ampersand should be storage.modifier.reference.php 514 | 515 | $foo = << 527 | 528 | HTML; 529 | 530 | // test 531 | 532 | $blah =<<test() 623 | /* something */ 624 | ->blah() 625 | // test 626 | ->oneMore(); 627 | 628 | $blah = "INSERT INTO foo SET blah = '12"; // Unclosed single quote should not be a problem 629 | $blah = "INSERT INTO `catalogue` SET 630 | `model`='{$_POST["page_row{$count}_model"]}', 631 | `type`='{$_POST["page_row{$count}_type"]}' 632 | ;"); 633 | 634 | $str = 'foo' . 'bar'; 635 | $str .= 'foo'; 636 | 637 | $x = 0; 638 | $x++; 639 | $y--; 640 | $x += 1; 641 | $x -= 1; 642 | $y = 2; 643 | 644 | $x = $x + $y; 645 | $x = $x - $y; 646 | $x = $x / $y; 647 | $x = $x * $y; 648 | $x = $x % $y; 649 | $x = $x << $y; 650 | $x = $x >> $y; 651 | $x = $x ~ $y; 652 | $x = $x ^ $y; 653 | $x = $x & $y; 654 | $x = $x | $y; 655 | 656 | $bar =& foo(); 657 | $bar = &foo(); 658 | $baz =& $bar; 659 | $baz = &$bar; 660 | 661 | foo(&$bar); 662 | 663 | $x = $x || $y; 664 | $x = $x && $y; 665 | $x = $x and $y; 666 | $x = $x or $y; 667 | $x = $x xor $y; 668 | $x = $x as $y; 669 | 670 | if ($x == 0) { } 671 | if ($x === 0) { } 672 | if ($x != 0) { } 673 | if ($x !== 0) { } 674 | if ($x < 0) { } 675 | if ($x <= 0) { } 676 | if ($x > 0) { } 677 | if ($x >= 0) { } 678 | if ($x <= 0) { } 679 | if ($x <> 0) { } 680 | 681 | $arr = array(1, 2, 3); 682 | $arr = array(array(1, 2, 3), array(1, 2, 3)); 683 | 684 | $foo(); 685 | $$foo(); 686 | 687 | if (true and false) {} 688 | if (true or (true and false)) {} 689 | 690 | $blah = (binary) $foo; 691 | $blah = (int) $foo; 692 | $blah = (integer) $foo; 693 | $blah = (bool) $foo; 694 | $blah = (boolean) $foo; 695 | $blah = (float) $foo; 696 | $blah = (double) $foo; 697 | $blah = (real) $foo; 698 | $blah = (string) $foo; 699 | $blah = (array) $foo; 700 | $blah = (object) $foo; 701 | $blah = (unset) $foo; 702 | 703 | ?> -------------------------------------------------------------------------------- /Tests/uncommon-comments.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | contactEmailRot13 6 | pvnjny@tznvy.pbz 7 | contactName 8 | Ciarán Walsh 9 | deleted 10 | 11 | 6FABC1A4-8CD0-11D9-B507-000D93C8BE28 12 | D723521E-CC93-419A-8056-D5178F28615B 13 | 9E187BE5-3E25-49A1-9FA1-D7EF18DF027D 14 | ADE95F8E-EC59-482C-AAD6-0212D5D7AB61 15 | C65A0A03-956D-11D9-B0A1-000D93382786 16 | FDFDEE91-956D-11D9-B0A1-000D93382786 17 | 13266D30-956E-11D9-B0A1-000D93382786 18 | 2CDD1B21-956E-11D9-B0A1-000D93382786 19 | 20 | description 21 | <a href="http://www.php.net/">PHP</a> is a widely-used general-purpose scripting language that is especially suited for web development and can be embedded into HTML. 22 | mainMenu 23 | 24 | excludedItems 25 | 26 | 26BC937A-5A0B-493E-B51F-1AF6E6FEFAD4 27 | 6F7E7868-F5A2-4B7D-ACFB-2A8DE2CD04E2 28 | 89385241-0117-42AE-BDAE-0471554CC3DF 29 | 647C793F-9098-481B-8B5A-BCEF3B48CB03 30 | E0FF5942-5249-4097-A4EE-E01FAE518CD2 31 | 32 | items 33 | 34 | 774E75DA-A747-4CB4-B8AF-DE720B01E295 35 | EC271DAE-BEC9-11D9-8856-000D93589AF6 36 | F82CE7A9-5E20-4B01-95EE-85255FB5A489 37 | B3E79B47-40E9-4EF9-BAD9-11FEEE0D238F 38 | ------------------------------------ 39 | 412481DC-89B7-11D9-9FE3-000A9584EC8C 40 | 19A164B7-4A3C-421B-9866-85FB9077A983 41 | 7E7936B6-7334-455B-A5ED-D51CA49CF532 42 | ------------------------------------ 43 | D2D8EC3B-7ABB-4309-BF61-438772AF1404 44 | C8984E70-D940-4477-B3F7-B0EB6F949012 45 | A3930E6A-FFFE-4E60-B797-052D34824F68 46 | ------------------------------------ 47 | DC9A3E58-34D0-4BD3-9D86-944F5DAC76A8 48 | ------------------------------------ 49 | 46E85E86-E85A-40EB-BC7A-0F06BC4AE9FB 50 | ------------------------------------ 51 | 8AAEC70A-8CCF-11D9-B507-000D93C8BE28 52 | A94E02E2-8CCF-11D9-B507-000D93C8BE28 53 | 60129434-8CCF-11D9-B507-000D93C8BE28 54 | 6E25DCEF-8CCF-11D9-B507-000D93C8BE28 55 | 34E2C808-8CCF-11D9-B507-000D93C8BE28 56 | 4833C612-8CCF-11D9-B507-000D93C8BE28 57 | ------------------------------------ 58 | 2B91DE5F-8CD0-11D9-B507-000D93C8BE28 59 | 1634287E-035A-4617-9AD8-09133183F8FE 60 | CBF8F204-8CCF-11D9-B507-000D93C8BE28 61 | 7720523B-8CCE-11D9-B507-000D93C8BE28 62 | ------------------------------------ 63 | C81F7FF7-7899-48F5-AD79-F248B7BC3DCB 64 | 65 | submenus 66 | 67 | 46E85E86-E85A-40EB-BC7A-0F06BC4AE9FB 68 | 69 | items 70 | 71 | 6F3ABAC6-EEC9-4797-8D4A-6FD549094852 72 | 9C891C7B-CFA8-4860-B76F-4E3AD60B0E13 73 | 74 | name 75 | Support 76 | 77 | 93896C6F-4D1B-47EA-94B2-887CAB6ABFC2 78 | 79 | items 80 | 81 | BB471E3A-8CCD-11D9-B507-000D93C8BE28 82 | 117476CE-7A7F-4DC4-9A4E-772D282983A3 83 | ED759470-69D7-4ADF-9842-D890DEB00F19 84 | 4F33617A-80FE-47D2-84AF-AA3D5D8A7128 85 | E863B097-0FD5-43D5-8547-235330081203 86 | 3F335934-360B-40F2-9D5C-CB299FD2F215 87 | 1E34E416-CD16-4C16-A369-9CDC3FAFD4C4 88 | 5F800F2D-55DA-4E06-99A3-41B734C8768E 89 | 7553818C-6FF8-455D-BD83-D2A587BAF6F4 90 | 91 | name 92 | Wrapped in <?php … ?> 93 | 94 | A3930E6A-FFFE-4E60-B797-052D34824F68 95 | 96 | items 97 | 98 | 80D861BF-8CD0-11D9-B507-000D93C8BE28 99 | 459B8A24-8CD0-11D9-B507-000D93C8BE28 100 | 56873C6E-8CD0-11D9-B507-000D93C8BE28 101 | 102 | name 103 | Return 104 | 105 | C8984E70-D940-4477-B3F7-B0EB6F949012 106 | 107 | items 108 | 109 | E8BDF86F-8CD0-11D9-B507-000D93C8BE28 110 | 9B253562-8CD0-11D9-B507-000D93C8BE28 111 | B90F3AE5-8CD0-11D9-B507-000D93C8BE28 112 | FF0A8A5C-8CD0-11D9-B507-000D93C8BE28 113 | CF29C6B5-8CD0-11D9-B507-000D93C8BE28 114 | 4E18C61F-8CD1-11D9-B507-000D93C8BE28 115 | 19B4F695-8CD1-11D9-B507-000D93C8BE28 116 | 306E5B79-8CD1-11D9-B507-000D93C8BE28 117 | 40A7709D-8CD1-11D9-B507-000D93C8BE28 118 | 119 | name 120 | Globals 121 | 122 | D2D8EC3B-7ABB-4309-BF61-438772AF1404 123 | 124 | items 125 | 126 | 93896C6F-4D1B-47EA-94B2-887CAB6ABFC2 127 | ------------------------------------ 128 | 35F46C2E-8CCE-11D9-B507-000D93C8BE28 129 | 4B72EA1F-8CCE-11D9-B507-000D93C8BE28 130 | 609FE8EB-B251-11D9-872D-000D93C8BE28 131 | 61DCF7E4-8CCE-11D9-B507-000D93C8BE28 132 | AC5561AA-8CCE-11D9-B507-000D93C8BE28 133 | C0229432-8CCE-11D9-B507-000D93C8BE28 134 | DA4B6728-8CCE-11D9-B507-000D93C8BE28 135 | F262B1FA-8CCE-11D9-B507-000D93C8BE28 136 | 0D955946-8CCF-11D9-B507-000D93C8BE28 137 | 1C06D786-8CCF-11D9-B507-000D93C8BE28 138 | 0F39268F-8CD0-11D9-B507-000D93C8BE28 139 | EC96DA26-8CCF-11D9-B507-000D93C8BE28 140 | DF786227-F5C9-48A1-8C80-49306AE82B6A 141 | ------------------------------------ 142 | C1B97DFD-7F2E-4CF8-881D-F63843DE8BD5 143 | ------------------------------------ 144 | FE39640E-A69C-48DF-9282-633672AAEFD2 145 | F7751DAF-AC95-4D47-955F-FE2534FDE4F5 146 | 978B5E5E-F5C6-4FD8-B346-B0C85883D600 147 | 148 | name 149 | Declarations 150 | 151 | DC9A3E58-34D0-4BD3-9D86-944F5DAC76A8 152 | 153 | items 154 | 155 | EBD6D4CF-9F5E-4616-9880-5D3FF21EF408 156 | 42F50AE3-4F1C-43EB-9722-D80261A19625 157 | ------------------------------------ 158 | 775F7FCC-C43C-4C23-B935-9D5F6C25CF1D 159 | 94D8B40B-9F49-4B6D-90B5-DBFF5FB36590 160 | ------------------------------------ 161 | 9086BA3F-87E7-11D9-A6A3-000D93589AF6 162 | 90879700-87E7-11D9-A6A3-000D93589AF6 163 | ------------------------------------ 164 | 9086E254-87E7-11D9-A6A3-000D93589AF6 165 | ------------------------------------ 166 | 9087051B-87E7-11D9-A6A3-000D93589AF6 167 | 908774B1-87E7-11D9-A6A3-000D93589AF6 168 | ------------------------------------ 169 | 90872B90-87E7-11D9-A6A3-000D93589AF6 170 | 90874D6F-87E7-11D9-A6A3-000D93589AF6 171 | 172 | name 173 | PHPDoc 174 | 175 | 176 | 177 | name 178 | PHP 179 | ordering 180 | 181 | E8BDF86F-8CD0-11D9-B507-000D93C8BE28 182 | 9B253562-8CD0-11D9-B507-000D93C8BE28 183 | B90F3AE5-8CD0-11D9-B507-000D93C8BE28 184 | FF0A8A5C-8CD0-11D9-B507-000D93C8BE28 185 | CF29C6B5-8CD0-11D9-B507-000D93C8BE28 186 | 4E18C61F-8CD1-11D9-B507-000D93C8BE28 187 | 19B4F695-8CD1-11D9-B507-000D93C8BE28 188 | 306E5B79-8CD1-11D9-B507-000D93C8BE28 189 | 40A7709D-8CD1-11D9-B507-000D93C8BE28 190 | BB471E3A-8CCD-11D9-B507-000D93C8BE28 191 | 117476CE-7A7F-4DC4-9A4E-772D282983A3 192 | ED759470-69D7-4ADF-9842-D890DEB00F19 193 | 1E34E416-CD16-4C16-A369-9CDC3FAFD4C4 194 | E863B097-0FD5-43D5-8547-235330081203 195 | 4F33617A-80FE-47D2-84AF-AA3D5D8A7128 196 | 3F335934-360B-40F2-9D5C-CB299FD2F215 197 | C1B97DFD-7F2E-4CF8-881D-F63843DE8BD5 198 | 26BC937A-5A0B-493E-B51F-1AF6E6FEFAD4 199 | 9C891C7B-CFA8-4860-B76F-4E3AD60B0E13 200 | 6F3ABAC6-EEC9-4797-8D4A-6FD549094852 201 | 90879700-87E7-11D9-A6A3-000D93589AF6 202 | 9086BA3F-87E7-11D9-A6A3-000D93589AF6 203 | 9086E254-87E7-11D9-A6A3-000D93589AF6 204 | 908774B1-87E7-11D9-A6A3-000D93589AF6 205 | 9087051B-87E7-11D9-A6A3-000D93589AF6 206 | 90872B90-87E7-11D9-A6A3-000D93589AF6 207 | 90874D6F-87E7-11D9-A6A3-000D93589AF6 208 | 775F7FCC-C43C-4C23-B935-9D5F6C25CF1D 209 | 0F39268F-8CD0-11D9-B507-000D93C8BE28 210 | 8AAEC70A-8CCF-11D9-B507-000D93C8BE28 211 | A94E02E2-8CCF-11D9-B507-000D93C8BE28 212 | 1C06D786-8CCF-11D9-B507-000D93C8BE28 213 | 2B91DE5F-8CD0-11D9-B507-000D93C8BE28 214 | 609FE8EB-B251-11D9-872D-000D93C8BE28 215 | 61DCF7E4-8CCE-11D9-B507-000D93C8BE28 216 | AC5561AA-8CCE-11D9-B507-000D93C8BE28 217 | C0229432-8CCE-11D9-B507-000D93C8BE28 218 | EC96DA26-8CCF-11D9-B507-000D93C8BE28 219 | DF786227-F5C9-48A1-8C80-49306AE82B6A 220 | 1634287E-035A-4617-9AD8-09133183F8FE 221 | 7720523B-8CCE-11D9-B507-000D93C8BE28 222 | 4B72EA1F-8CCE-11D9-B507-000D93C8BE28 223 | 35F46C2E-8CCE-11D9-B507-000D93C8BE28 224 | 34E2C808-8CCF-11D9-B507-000D93C8BE28 225 | 4833C612-8CCF-11D9-B507-000D93C8BE28 226 | CBF8F204-8CCF-11D9-B507-000D93C8BE28 227 | 60129434-8CCF-11D9-B507-000D93C8BE28 228 | 6E25DCEF-8CCF-11D9-B507-000D93C8BE28 229 | 80D861BF-8CD0-11D9-B507-000D93C8BE28 230 | 56873C6E-8CD0-11D9-B507-000D93C8BE28 231 | 459B8A24-8CD0-11D9-B507-000D93C8BE28 232 | F262B1FA-8CCE-11D9-B507-000D93C8BE28 233 | DA4B6728-8CCE-11D9-B507-000D93C8BE28 234 | FE39640E-A69C-48DF-9282-633672AAEFD2 235 | F7751DAF-AC95-4D47-955F-FE2534FDE4F5 236 | 0D955946-8CCF-11D9-B507-000D93C8BE28 237 | 978B5E5E-F5C6-4FD8-B346-B0C85883D600 238 | 7E7936B6-7334-455B-A5ED-D51CA49CF532 239 | 42F50AE3-4F1C-43EB-9722-D80261A19625 240 | 19A164B7-4A3C-421B-9866-85FB9077A983 241 | C81F7FF7-7899-48F5-AD79-F248B7BC3DCB 242 | B3E79B47-40E9-4EF9-BAD9-11FEEE0D238F 243 | 412481DC-89B7-11D9-9FE3-000A9584EC8C 244 | EBD6D4CF-9F5E-4616-9880-5D3FF21EF408 245 | 94D8B40B-9F49-4B6D-90B5-DBFF5FB36590 246 | 774E75DA-A747-4CB4-B8AF-DE720B01E295 247 | EC271DAE-BEC9-11D9-8856-000D93589AF6 248 | 6F7E7868-F5A2-4B7D-ACFB-2A8DE2CD04E2 249 | B5E34751-D5EB-4AC8-9DB1-779BD6489C76 250 | 22986475-8CA5-11D9-AEDD-000D93C8BE28 251 | 06276449-AA4E-424F-A2B6-9F4138416E50 252 | CBE2288F-76FC-4813-B69B-B90FFAE3391C 253 | 2543E52B-D5CF-4BBE-B792-51F1574EA05F 254 | FD4397A8-415F-47BC-9F8D-E0F0EC364286 255 | E2D08D2E-A99C-4F3A-9B1D-05A75D37A819 256 | CA15DF69-E80D-46DA-BD45-E88C68E92117 257 | F15B444C-13E3-4A3C-83E1-4A6E0C1A84F3 258 | 5157F71C-2801-4385-92EA-3D0B72AEE7C5 259 | 77F2D17D-A48A-4E19-B2A4-B2FBCBD1264D 260 | 998BFB01-C049-4A24-A88E-86173C967748 261 | 89385241-0117-42AE-BDAE-0471554CC3DF 262 | E0FF5942-5249-4097-A4EE-E01FAE518CD2 263 | 647C793F-9098-481B-8B5A-BCEF3B48CB03 264 | 5F800F2D-55DA-4E06-99A3-41B734C8768E 265 | 7553818C-6FF8-455D-BD83-D2A587BAF6F4 266 | 267 | uuid 268 | 467A1966-6227-11D9-BFB1-000D93589AF6 269 | 270 | 271 | --------------------------------------------------------------------------------