{"action":"created","issue":{"url":"https://api.github.com/repos/github/linguist/issues/2749","labels_url":"https://api.github.com/repos/github/linguist/issues/2749/labels{/name}","comments_url":"https://api.github.com/repos/github/linguist/issues/2749/comments","events_url":"https://api.github.com/repos/github/linguist/issues/2749/events","html_url":"https://github.com/github/linguist/pull/2749","id":119233368,"number":2749,"title":"Add language support for MAXScript","user":{"login":"Alhadis","id":2346707,"avatar_url":"https://avatars.githubusercontent.com/u/2346707?v=3","gravatar_id":"","url":"https://api.github.com/users/Alhadis","html_url":"https://github.com/Alhadis","followers_url":"https://api.github.com/users/Alhadis/followers","following_url":"https://api.github.com/users/Alhadis/following{/other_user}","gists_url":"https://api.github.com/users/Alhadis/gists{/gist_id}","starred_url":"https://api.github.com/users/Alhadis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Alhadis/subscriptions","organizations_url":"https://api.github.com/users/Alhadis/orgs","repos_url":"https://api.github.com/users/Alhadis/repos","events_url":"https://api.github.com/users/Alhadis/events{/privacy}","received_events_url":"https://api.github.com/users/Alhadis/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-11-27T18:25:30Z","updated_at":"2015-11-27T18:48:24Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/github/linguist/pulls/2749","html_url":"https://github.com/github/linguist/pull/2749","diff_url":"https://github.com/github/linguist/pull/2749.diff","patch_url":"https://github.com/github/linguist/pull/2749.patch"},"body":"This PR adds support for MAXScript, the built-in scripting language for [3ds Max](https://en.wikipedia.org/wiki/Autodesk_3ds_Max).\r\n\r\nUsage\r\n-----\r\n\r\nMAXScript isn't exactly kicking JavaScript in terms of popularity, to say the least, but there's enough in-the-wild usage to warrant the language's inclusion on GitHub:\r\n\r\n* [extension:ms fn](https://github.com/search?q=extension%3Ams+fn) (~6,610 results)\r\n* [extension:ms function](https://github.com/search?q=extension%3Ams+function) (~13,470 results)\r\n\r\n[ScriptSpot](http://www.scriptspot.com/) has been a well-known and popular resource for MAXScripts since at [least 2000](http://www.scriptspot.com/3ds-max/plugins/maxscribe), although the site's maintenance appears to have declined sharply in recent years. It's probably as good a time as any to introduce formal support for MAXScript on GitHub, which may encourage more MAXScripters to upload/share their work.\r\n\r\nHeuristic modifications\r\n-----------------------\r\n\r\nMAXScript already offers a `move` function, so we can't rely on the current heuristic of identifying GAS by the presence of a `move` command.\r\n\r\nMy initial approach was to check for Assembly-like statements like the following, since it'd be a syntax error in MAXScript:\r\n\r\n```\r\n.LGCOMMAND\r\n\t.now\r\n\t.return\r\n```\r\n\r\nHowever, because of MAXScript's fluidity, it's unreasonable to assume lengthy statements won't be broken across multiple lines:\r\n```\r\n\tvalue = colossal_plugin_struct_thing \\\r\n\t\t.calculate this mumbo:#jumbo\r\n\r\n\t-- That has the same effect as writing this:\r\n\tvalue = colossal_plugin_struct_thing.calculate this mumbo:#jumbo\r\n```\r\n\r\n\r\nIn other words, simply checking `\\n\\s*\\.[A-Za-z]` isn't good enough; we need to account for things like escaped line-breaks and string literals/comments:\r\n\r\n```rb\r\ndata.gsub(/\"([^\\\\\"]|\\\\.)*\"|'([^\\\\']|\\\\.)*'/, \"\").gsub(/\\\\\\s*(?:--.*)?\\n/, \"\\n\")\r\n```\r\n\r\nThis might be slight overkill, but it irons out any potential for misclassification.\r\n\r\n\r\n\r\nPerformance\r\n-----------\r\n\r\nI took the time to analyse the performance of different heuristics when run against a [repository of considerable size](https://github.com/Alhadis/Linguist-Heuristics-MS) (15,609 files, 1.4 GiBs). I've averaged the speed results below, but the full stats can be [viewed here](http://pastebin.com/EmLwT0xU) for anybody who's curious.\r\n\r\n\r\n### Original/Current `.ms` Heuristic\r\n\r\n```\r\n/((^|\\s)move?[. ])|\\.(include|globa?l)\\s/.match(data)\r\n\r\nAverage speed (10 runs):\r\n\treal    39.8s\r\n\tuser    38.9869s\r\n\tsys     0.8023s\r\n```\r\n\r\n\r\n\r\n### Amended Heuristic\r\n\r\n```\r\n/(?<!\\S)\\.(include|globa?l)\\s/.match(data) || \r\n\t/(?<!\\/\\*)(\\A|\\n)\\s*\\.[A-Za-z]/.match(data.gsub(/\"([^\\\\\"]|\\\\.)*\"|'([^\\\\']|\\\\.)*'|\\\\\\s*(?:--.*)?\\n/, \"\"))\r\n\r\nAverage speed (10 runs):\r\n\treal    41.3077s\r\n\tuser    40.3206s\r\n\tsys     0.9744s\r\n```\r\n\r\n### Earlier variations:\r\nThese are potentially slightly faster, but offer a little less accuracy:\r\n\r\n```\r\n/(?<!\\S)\\.(include|globa?l)\\s/.match(data) ||\r\n\t/(?<!\\/\\*)(\\A|\\n)\\s*\\.[A-Za-z]/.match(data.sub(/\"([^\\\\\"]|\\\\.)*\"|'([^\\\\']|\\\\.)*'/, \"\"))\r\n\r\nAverage speed (10 runs):\r\n\treal    40.0s\r\n\tuser    39.1899s\r\n\tsys     0.7947s\r\n```\r\n\r\n```\r\n/(?<!\\S)\\.(include|globa?l)\\s/.match(data) || /(?<!\\/\\*)(\\A|\\n)\\s*\\.[A-Za-z]/.match(data)\r\n\r\nAverage speed (10 runs):\r\n\treal    38.9172s\r\n\tuser    38.1532s\r\n\tsys     0.7561s\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/github/linguist/issues/comments/160189200","html_url":"https://github.com/github/linguist/pull/2749#issuecomment-160189200","issue_url":"https://api.github.com/repos/github/linguist/issues/2749","id":160189200,"user":{"login":"larsbrinkhoff","id":775050,"avatar_url":"https://avatars.githubusercontent.com/u/775050?v=3","gravatar_id":"","url":"https://api.github.com/users/larsbrinkhoff","html_url":"https://github.com/larsbrinkhoff","followers_url":"https://api.github.com/users/larsbrinkhoff/followers","following_url":"https://api.github.com/users/larsbrinkhoff/following{/other_user}","gists_url":"https://api.github.com/users/larsbrinkhoff/gists{/gist_id}","starred_url":"https://api.github.com/users/larsbrinkhoff/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/larsbrinkhoff/subscriptions","organizations_url":"https://api.github.com/users/larsbrinkhoff/orgs","repos_url":"https://api.github.com/users/larsbrinkhoff/repos","events_url":"https://api.github.com/users/larsbrinkhoff/events{/privacy}","received_events_url":"https://api.github.com/users/larsbrinkhoff/received_events","type":"User","site_admin":false},"created_at":"2015-11-27T18:48:24Z","updated_at":"2015-11-27T18:48:24Z","body":"It would be nice if your updated `.ms` heuristics added some matching function for MAXScript, rather than a catch-all `else`."}}