{"action":"created","comment":{"url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/comments/36544936","id":36544936,"diff_hunk":"@@ -1,44 +1,494 @@\n --- === hs.geometry ===\n ---\n---- Utility functions for math operations and constructing geometric objects (rects/points/etc)\n+--- Utility object to represent points, sizes and rects in a bidimensional plane\n+---\n+--- An hs.geometry object can be:\n+---  * a *point*, or vector2, with `x` and `y` fields for its coordinates\n+---  * a *size* with `w` and `h` fields for width and heigth respectively\n+---  * a *rect*, which has both a point component for one of its corners, and a size component - so it has all 4 fields\n+---\n+--- You can create these objects in many different ways, via `my_obj=hs.geometry.new(...)` or simply `my_obj=hs.geometry(...)`\n+--- by passing any of the following:\n+---  * 4 parameters `X,Y,W,H` for the respective fields - W and H, or X and Y, can be `nil`:\n+---    * `hs.geometry(X,Y)` creates a point\n+---    * `hs.geometry(nil,nil,W,H)` creates a size\n+---    * `hs.geometry(X,Y,W,H)` creates a rect given its width and heigth from a corner\n+---  * a table `{X,Y}` creates a point\n+---  * a table `{X,Y,W,H}` creates a rect\n+---  * a table `{x=X,y=Y,w=W,h=H}` creates a rect, or if you omit X and Y, or W and H, creates a size or a point respectively\n+---  * a table `{x1=X1,y1=Y1,x2=X2,y2=Y2}` creates a rect, where X1,Y1 and X2,Y2 are the coordinates of opposite corners\n+---  * a string:\n+---    * `\"X Y\"` or `\"X,Y\"` creates a point\n+---    * `\"WxH\"` or `\"W*H\"` creates a size\n+---    * `\"X Y WxH\"` or `\"X,Y/W*H\"` (or variations thereof) creates a rect given its width and heigth from a corner\n+---    * `\"X1 Y1 > X2 Y2\"` or `\"X1,Y1,X2,Y2\"` (or variations thereof) creates a rect given two opposite corners\n+---\n+--- You can use any of these anywhere an hs.geometry object is expected in Hammerspoon; the constructor will be called for you.\n \n-local geometry = require \"hs.geometry.internal\"\n+-- remove copy-on-new\n+--  * another `hs.geometry` object - creates a copy of that object\n \n---- hs.geometry.rotateCCW(point, aroundpoint, ntimes = 1) -> point\n---- Function\n---- Rotates a point around another point N times\n+--TODO allow segments? (like rects, but no norm())\n+\n+local rawget,rawset,type,pairs,tonumber,sqrt=rawget,rawset,type,pairs,tonumber,math.sqrt\n+local min,max,atan,smatch,sformat=math.min,math.max,math.atan,string.match,string.format\n+local getmetatable,setmetatable=getmetatable,setmetatable\n+\n+local geometry = {}--require \"hs.geometry.internal\"\n+\n+local ws=' *'\n+local sepout=ws..'([ ,>/])'..ws\n+local sepin=ws..'([ x*,])'..ws\n+local number='(%-?%d*%.?%d*)'\n+local function parse(s)\n+  local x,y,w,h\n+  local sept,n3,sep2,n4\n+  local n1,sep1,n2,i = smatch(s,number..sepin..number..'()')\n+  if i then sept,n3,sep2,n4 = smatch(s,sepout..number..sepin..number,i) end\n+  if sep1=='x' or sep1=='*' then --it's a size\n+    w=tonumber(n1) h=tonumber(n2)\n+    if not w then error('Cannot parse width',3) end\n+    if not h then error('Cannot parse heigth',3) end\n+  else\n+    x=tonumber(n1) y=tonumber(n2)\n+    if not x then error('Cannot parse x coord',3) end\n+    if not y then error('Cannot parse y coord',3) end\n+    if sept=='>' or sep2==' ' or sep2==',' then --it's a rectx2y2\n+      w=tonumber(n3)-x h=tonumber(n4)-y\n+      if not w then error('Cannot parse x2 coord',3) end\n+      if not h then error('Cannot parse y2 coord',3) end\n+    elseif sep2 then --it's a rectsize\n+      w=tonumber(n3) h=tonumber(n4)\n+      if not w then error('Cannot parse width',3) end\n+      if not h then error('Cannot parse heigth',3) end\n+    end\n+  end\n+  return x,y,w,h\n+end\n+\n+local function gettype(t)\n+  if t._x and t._y then\n+    if t._w and t._h then return 'rect' else return 'point' end\n+  elseif t._w and t._h then return 'size' end\n+end\n+local function norm(t)\n+  if t._x and t._w and t._w<0 then t._x=t._x+t._w t._w=-t._w end\n+  if t._y and t._h and t._h<0 then t._y=t._y+t._h t._h=-t._h end\n+end\n+\n+local function new(x,y,w,h)\n+  if getmetatable(x)==geometry then return x end -- disable copy-on-new\n+  if type(x)=='string' then\n+    x,y,w,h=parse(x)\n+  elseif type(x)=='table' then\n+    if x[1] then x,y,w,h=x[1],x[2],x[3],x[4]\n+    else\n+      local t=x\n+      x,y=t.x or t.x1,t.y or t.y1\n+      w,h=t.w or t.x2-x,t.h or t.y2-y\n+    end\n+  end\n+  local t={_x=x,_y=y,_w=w,_h=h}\n+  for k,v in pairs(t) do if type(v)~='number' then t[k]=nil end end\n+  norm(t)\n+  if not gettype(t) then error('Cannot create geometry object, wrong arguments',2) end\n+  return setmetatable(t,geometry)\n+end\n+--- hs.geometry.new(...) -> hs.geometry","path":"extensions/geometry/init.lua","position":102,"original_position":102,"commit_id":"1b1bc69606c8fbfd5585323ebc0c3bea2593e460","original_commit_id":"1b1bc69606c8fbfd5585323ebc0c3bea2593e460","user":{"login":"cmsj","id":353427,"avatar_url":"https://avatars.githubusercontent.com/u/353427?v=3","gravatar_id":"","url":"https://api.github.com/users/cmsj","html_url":"https://github.com/cmsj","followers_url":"https://api.github.com/users/cmsj/followers","following_url":"https://api.github.com/users/cmsj/following{/other_user}","gists_url":"https://api.github.com/users/cmsj/gists{/gist_id}","starred_url":"https://api.github.com/users/cmsj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmsj/subscriptions","organizations_url":"https://api.github.com/users/cmsj/orgs","repos_url":"https://api.github.com/users/cmsj/repos","events_url":"https://api.github.com/users/cmsj/events{/privacy}","received_events_url":"https://api.github.com/users/cmsj/received_events","type":"User","site_admin":false},"body":"I'm not a fan of having \"hs.geometry\" as the return type. We're not very consistent about this yet, but I think the word \"object\" needs to be in there - maybe \"geometry object\"?","created_at":"2015-08-07T18:08:36Z","updated_at":"2015-08-07T18:08:36Z","html_url":"https://github.com/Hammerspoon/hammerspoon/pull/471#discussion_r36544936","pull_request_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471","_links":{"self":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/comments/36544936"},"html":{"href":"https://github.com/Hammerspoon/hammerspoon/pull/471#discussion_r36544936"},"pull_request":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471"}}},"pull_request":{"url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471","id":41804971,"html_url":"https://github.com/Hammerspoon/hammerspoon/pull/471","diff_url":"https://github.com/Hammerspoon/hammerspoon/pull/471.diff","patch_url":"https://github.com/Hammerspoon/hammerspoon/pull/471.patch","issue_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/471","number":471,"state":"open","locked":false,"title":"hs.geometry overhaul","user":{"login":"lowne","id":6718755,"avatar_url":"https://avatars.githubusercontent.com/u/6718755?v=3","gravatar_id":"","url":"https://api.github.com/users/lowne","html_url":"https://github.com/lowne","followers_url":"https://api.github.com/users/lowne/followers","following_url":"https://api.github.com/users/lowne/following{/other_user}","gists_url":"https://api.github.com/users/lowne/gists{/gist_id}","starred_url":"https://api.github.com/users/lowne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lowne/subscriptions","organizations_url":"https://api.github.com/users/lowne/orgs","repos_url":"https://api.github.com/users/lowne/repos","events_url":"https://api.github.com/users/lowne/events{/privacy}","received_events_url":"https://api.github.com/users/lowne/received_events","type":"User","site_admin":false},"body":"> 17:47 lowne: > g'0 0 100 100'..'80 80 50x50'\r\n17:47 lowne: hs.geometry.rect(0,0,130,130)\r\n17:47 lowne: > g'0 0 100 100'^'80 80 50x50'\r\n17:47 lowne: hs.geometry.rect(80,80,20,20)\r\n17:48 lowne: > g'5 5'<'0 0 10 10'\r\n17:48 lowne: true\r\n17:49 lowne: fun!\r\n\r\nBut:\r\n- there might be bugs, I didn't test everything yet\r\n- line segments (let alone orientated ones) aren't supported; would that be useful?\r\n- no fancy stuff for line intersections etc., see item above\r\n- according to the module docstring promise, stuff like :setFrame(f) in windows and drawings should wrap the parameter in `hs.geometry(arg)` - will do if this is deemed mergeable","created_at":"2015-08-06T16:03:52Z","updated_at":"2015-08-07T18:08:36Z","closed_at":null,"merged_at":null,"merge_commit_sha":"788b56b1e87b922ed8db9d0e721fe9dab3a95976","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471/commits","review_comments_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471/comments","review_comment_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/471/comments","statuses_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/statuses/1b1bc69606c8fbfd5585323ebc0c3bea2593e460","head":{"label":"lowne:geometry","ref":"geometry","sha":"1b1bc69606c8fbfd5585323ebc0c3bea2593e460","user":{"login":"lowne","id":6718755,"avatar_url":"https://avatars.githubusercontent.com/u/6718755?v=3","gravatar_id":"","url":"https://api.github.com/users/lowne","html_url":"https://github.com/lowne","followers_url":"https://api.github.com/users/lowne/followers","following_url":"https://api.github.com/users/lowne/following{/other_user}","gists_url":"https://api.github.com/users/lowne/gists{/gist_id}","starred_url":"https://api.github.com/users/lowne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lowne/subscriptions","organizations_url":"https://api.github.com/users/lowne/orgs","repos_url":"https://api.github.com/users/lowne/repos","events_url":"https://api.github.com/users/lowne/events{/privacy}","received_events_url":"https://api.github.com/users/lowne/received_events","type":"User","site_admin":false},"repo":{"id":37988150,"name":"hammerspoon","full_name":"lowne/hammerspoon","owner":{"login":"lowne","id":6718755,"avatar_url":"https://avatars.githubusercontent.com/u/6718755?v=3","gravatar_id":"","url":"https://api.github.com/users/lowne","html_url":"https://github.com/lowne","followers_url":"https://api.github.com/users/lowne/followers","following_url":"https://api.github.com/users/lowne/following{/other_user}","gists_url":"https://api.github.com/users/lowne/gists{/gist_id}","starred_url":"https://api.github.com/users/lowne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lowne/subscriptions","organizations_url":"https://api.github.com/users/lowne/orgs","repos_url":"https://api.github.com/users/lowne/repos","events_url":"https://api.github.com/users/lowne/events{/privacy}","received_events_url":"https://api.github.com/users/lowne/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lowne/hammerspoon","description":"Staggeringly powerful OS X desktop automation with Lua","fork":true,"url":"https://api.github.com/repos/lowne/hammerspoon","forks_url":"https://api.github.com/repos/lowne/hammerspoon/forks","keys_url":"https://api.github.com/repos/lowne/hammerspoon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lowne/hammerspoon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lowne/hammerspoon/teams","hooks_url":"https://api.github.com/repos/lowne/hammerspoon/hooks","issue_events_url":"https://api.github.com/repos/lowne/hammerspoon/issues/events{/number}","events_url":"https://api.github.com/repos/lowne/hammerspoon/events","assignees_url":"https://api.github.com/repos/lowne/hammerspoon/assignees{/user}","branches_url":"https://api.github.com/repos/lowne/hammerspoon/branches{/branch}","tags_url":"https://api.github.com/repos/lowne/hammerspoon/tags","blobs_url":"https://api.github.com/repos/lowne/hammerspoon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lowne/hammerspoon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lowne/hammerspoon/git/refs{/sha}","trees_url":"https://api.github.com/repos/lowne/hammerspoon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lowne/hammerspoon/statuses/{sha}","languages_url":"https://api.github.com/repos/lowne/hammerspoon/languages","stargazers_url":"https://api.github.com/repos/lowne/hammerspoon/stargazers","contributors_url":"https://api.github.com/repos/lowne/hammerspoon/contributors","subscribers_url":"https://api.github.com/repos/lowne/hammerspoon/subscribers","subscription_url":"https://api.github.com/repos/lowne/hammerspoon/subscription","commits_url":"https://api.github.com/repos/lowne/hammerspoon/commits{/sha}","git_commits_url":"https://api.github.com/repos/lowne/hammerspoon/git/commits{/sha}","comments_url":"https://api.github.com/repos/lowne/hammerspoon/comments{/number}","issue_comment_url":"https://api.github.com/repos/lowne/hammerspoon/issues/comments{/number}","contents_url":"https://api.github.com/repos/lowne/hammerspoon/contents/{+path}","compare_url":"https://api.github.com/repos/lowne/hammerspoon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lowne/hammerspoon/merges","archive_url":"https://api.github.com/repos/lowne/hammerspoon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lowne/hammerspoon/downloads","issues_url":"https://api.github.com/repos/lowne/hammerspoon/issues{/number}","pulls_url":"https://api.github.com/repos/lowne/hammerspoon/pulls{/number}","milestones_url":"https://api.github.com/repos/lowne/hammerspoon/milestones{/number}","notifications_url":"https://api.github.com/repos/lowne/hammerspoon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lowne/hammerspoon/labels{/name}","releases_url":"https://api.github.com/repos/lowne/hammerspoon/releases{/id}","created_at":"2015-06-24T14:06:36Z","updated_at":"2015-07-31T11:26:29Z","pushed_at":"2015-08-07T17:29:17Z","git_url":"git://github.com/lowne/hammerspoon.git","ssh_url":"git@github.com:lowne/hammerspoon.git","clone_url":"https://github.com/lowne/hammerspoon.git","svn_url":"https://github.com/lowne/hammerspoon","homepage":"http://www.hammerspoon.org","size":16098,"stargazers_count":0,"watchers_count":0,"language":"Objective-C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Hammerspoon:master","ref":"master","sha":"ae2c6b185bc04b014318dd14c24d4b2c45553238","user":{"login":"Hammerspoon","id":9214848,"avatar_url":"https://avatars.githubusercontent.com/u/9214848?v=3","gravatar_id":"","url":"https://api.github.com/users/Hammerspoon","html_url":"https://github.com/Hammerspoon","followers_url":"https://api.github.com/users/Hammerspoon/followers","following_url":"https://api.github.com/users/Hammerspoon/following{/other_user}","gists_url":"https://api.github.com/users/Hammerspoon/gists{/gist_id}","starred_url":"https://api.github.com/users/Hammerspoon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hammerspoon/subscriptions","organizations_url":"https://api.github.com/users/Hammerspoon/orgs","repos_url":"https://api.github.com/users/Hammerspoon/repos","events_url":"https://api.github.com/users/Hammerspoon/events{/privacy}","received_events_url":"https://api.github.com/users/Hammerspoon/received_events","type":"Organization","site_admin":false},"repo":{"id":24956772,"name":"hammerspoon","full_name":"Hammerspoon/hammerspoon","owner":{"login":"Hammerspoon","id":9214848,"avatar_url":"https://avatars.githubusercontent.com/u/9214848?v=3","gravatar_id":"","url":"https://api.github.com/users/Hammerspoon","html_url":"https://github.com/Hammerspoon","followers_url":"https://api.github.com/users/Hammerspoon/followers","following_url":"https://api.github.com/users/Hammerspoon/following{/other_user}","gists_url":"https://api.github.com/users/Hammerspoon/gists{/gist_id}","starred_url":"https://api.github.com/users/Hammerspoon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hammerspoon/subscriptions","organizations_url":"https://api.github.com/users/Hammerspoon/orgs","repos_url":"https://api.github.com/users/Hammerspoon/repos","events_url":"https://api.github.com/users/Hammerspoon/events{/privacy}","received_events_url":"https://api.github.com/users/Hammerspoon/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Hammerspoon/hammerspoon","description":"Staggeringly powerful OS X desktop automation with Lua","fork":false,"url":"https://api.github.com/repos/Hammerspoon/hammerspoon","forks_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/forks","keys_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/teams","hooks_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/hooks","issue_events_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/events{/number}","events_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/events","assignees_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/assignees{/user}","branches_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/branches{/branch}","tags_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/tags","blobs_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/git/refs{/sha}","trees_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/statuses/{sha}","languages_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/languages","stargazers_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/stargazers","contributors_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/contributors","subscribers_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/subscribers","subscription_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/subscription","commits_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/commits{/sha}","git_commits_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/git/commits{/sha}","comments_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/comments{/number}","issue_comment_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/comments{/number}","contents_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/contents/{+path}","compare_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/merges","archive_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/downloads","issues_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues{/number}","pulls_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls{/number}","milestones_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/milestones{/number}","notifications_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/labels{/name}","releases_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/releases{/id}","created_at":"2014-10-08T19:24:44Z","updated_at":"2015-08-07T11:38:47Z","pushed_at":"2015-08-07T17:59:51Z","git_url":"git://github.com/Hammerspoon/hammerspoon.git","ssh_url":"git@github.com:Hammerspoon/hammerspoon.git","clone_url":"https://github.com/Hammerspoon/hammerspoon.git","svn_url":"https://github.com/Hammerspoon/hammerspoon","homepage":"http://www.hammerspoon.org","size":18803,"stargazers_count":398,"watchers_count":398,"language":"Objective-C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":46,"mirror_url":null,"open_issues_count":84,"forks":46,"open_issues":84,"watchers":398,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471"},"html":{"href":"https://github.com/Hammerspoon/hammerspoon/pull/471"},"issue":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/471"},"comments":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/471/comments"},"review_comments":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471/comments"},"review_comment":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/471/commits"},"statuses":{"href":"https://api.github.com/repos/Hammerspoon/hammerspoon/statuses/1b1bc69606c8fbfd5585323ebc0c3bea2593e460"}}}}