{"action":"created","comment":{"url":"https://api.github.com/repos/facebook/PathPicker/pulls/comments/30003991","id":30003991,"diff_hunk":"@@ -0,0 +1,127 @@\n+# Copyright (c) 2015-present, Facebook, Inc.\n+# All rights reserved.\n+#\n+# This source code is licensed under the BSD-style license found in the\n+# LICENSE file in the root directory of this source tree. An additional grant\n+# of patent rights can be found in the PATENTS file in the same directory.\n+#\n+# @nolint\n+\n+import re\n+import curses\n+\n+class FormattedText(object):\n+    \"\"\"A piece of ANSI escape formatted text which responds\n+    to str() returning the plain text and knows how to print\n+    itself out using ncurses\"\"\"\n+\n+    ANSI_ESCAPE_FORMATTING = r'\\x1b\\[([^mK]*)[mK]'\n+    BOLD_ATTRIBUTE = 1\n+    UNDERLINE_ATTRIBUTE = 4\n+\n+    def __init__(self, text):\n+        self.text = text\n+\n+        self.segments = re.split(self.ANSI_ESCAPE_FORMATTING, self.text)\n+        #re.split will insert a empty string if there is a match at the beginning\n+        #or it will return [string] if there is no match\n+        #create the invariant that every segment has a formatting segment, e.g\n+        #we will always have FORMAT, TEXT, FORMAT, TEXT\n+        self.segments.insert(0, '')\n+        self.plainText = ''.join(self.segments[1::2])\n+\n+\n+    def __str__(self):\n+        return self.plainText\n+\n+    @classmethod\n+    def parseFormatting(cls, formatting):\n+        \"\"\"Parse ANSI formatting; the formatting passed in should be\n+        stripped of the control characters and ending character\"\"\"\n+        fore = -1 #-1 default means \"use default\", not \"use white/black\"\n+        back = -1\n+        other = 0\n+        intValues = [int(value) for value in formatting.split(';') if value]\n+        for code in intValues:\n+            if code >= 30 and code <= 39:","path":"src/formattedText.py","position":46,"original_position":46,"commit_id":"d6221337bdf0275cf03003f38a82c3c277d303a8","original_commit_id":"d6221337bdf0275cf03003f38a82c3c277d303a8","user":{"login":"pcottle","id":1135007,"avatar_url":"https://avatars.githubusercontent.com/u/1135007?v=3","gravatar_id":"","url":"https://api.github.com/users/pcottle","html_url":"https://github.com/pcottle","followers_url":"https://api.github.com/users/pcottle/followers","following_url":"https://api.github.com/users/pcottle/following{/other_user}","gists_url":"https://api.github.com/users/pcottle/gists{/gist_id}","starred_url":"https://api.github.com/users/pcottle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pcottle/subscriptions","organizations_url":"https://api.github.com/users/pcottle/orgs","repos_url":"https://api.github.com/users/pcottle/repos","events_url":"https://api.github.com/users/pcottle/events{/privacy}","received_events_url":"https://api.github.com/users/pcottle/received_events","type":"User","site_admin":false},"body":"should these `30` and `40`'s be constants in the class? then we could at least explain what they mean and there would be less magic numbers here","created_at":"2015-05-10T17:04:19Z","updated_at":"2015-05-10T17:04:19Z","html_url":"https://github.com/facebook/PathPicker/pull/53#discussion_r30003991","pull_request_url":"https://api.github.com/repos/facebook/PathPicker/pulls/53","_links":{"self":{"href":"https://api.github.com/repos/facebook/PathPicker/pulls/comments/30003991"},"html":{"href":"https://github.com/facebook/PathPicker/pull/53#discussion_r30003991"},"pull_request":{"href":"https://api.github.com/repos/facebook/PathPicker/pulls/53"}}},"pull_request":{"url":"https://api.github.com/repos/facebook/PathPicker/pulls/53","id":34997530,"html_url":"https://github.com/facebook/PathPicker/pull/53","diff_url":"https://github.com/facebook/PathPicker/pull/53.diff","patch_url":"https://github.com/facebook/PathPicker/pull/53.patch","issue_url":"https://api.github.com/repos/facebook/PathPicker/issues/53","number":53,"state":"open","locked":false,"title":"ANSI color support","user":{"login":"lastquestion","id":1095956,"avatar_url":"https://avatars.githubusercontent.com/u/1095956?v=3","gravatar_id":"","url":"https://api.github.com/users/lastquestion","html_url":"https://github.com/lastquestion","followers_url":"https://api.github.com/users/lastquestion/followers","following_url":"https://api.github.com/users/lastquestion/following{/other_user}","gists_url":"https://api.github.com/users/lastquestion/gists{/gist_id}","starred_url":"https://api.github.com/users/lastquestion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lastquestion/subscriptions","organizations_url":"https://api.github.com/users/lastquestion/orgs","repos_url":"https://api.github.com/users/lastquestion/repos","events_url":"https://api.github.com/users/lastquestion/events{/privacy}","received_events_url":"https://api.github.com/users/lastquestion/received_events","type":"User","site_admin":false},"body":"~~This is a shitty first pass at colors that I hacked together because I couldn't sleep.~~ Now better!\r\n\r\nTurns out `ncurses` doesn't really support (AFAIK, someone please correct me...) setting foreground/background color combinations directly, so I cache and create `color_pair` as I go along. Most terms have at least 32 and mine on OSX seems to have 256.\r\n\r\nI'm also totally not a python developer, so the code here is probably quite not idomatic.\r\n\r\nScreencap because I don't know how to do that cool video thing:\r\nthe command was `git diff --color | fpp`\r\n![screen shot 2015-05-08 at 3 30 50 am](https://cloud.githubusercontent.com/assets/1095956/7534766/a7436092-f532-11e4-8cc1-8f53c0873342.png)\r\n\r\nThings to improve on\r\n* Make the chrome use colors instead of hardcoding `color_pair(0)`.","created_at":"2015-05-08T10:34:33Z","updated_at":"2015-05-10T17:04:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d478e00ae7d5cfa67af98ba4583fe4ad384e5dbb","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/facebook/PathPicker/pulls/53/commits","review_comments_url":"https://api.github.com/repos/facebook/PathPicker/pulls/53/comments","review_comment_url":"https://api.github.com/repos/facebook/PathPicker/pulls/comments{/number}","comments_url":"https://api.github.com/repos/facebook/PathPicker/issues/53/comments","statuses_url":"https://api.github.com/repos/facebook/PathPicker/statuses/d6221337bdf0275cf03003f38a82c3c277d303a8","head":{"label":"lastquestion:colors","ref":"colors","sha":"d6221337bdf0275cf03003f38a82c3c277d303a8","user":{"login":"lastquestion","id":1095956,"avatar_url":"https://avatars.githubusercontent.com/u/1095956?v=3","gravatar_id":"","url":"https://api.github.com/users/lastquestion","html_url":"https://github.com/lastquestion","followers_url":"https://api.github.com/users/lastquestion/followers","following_url":"https://api.github.com/users/lastquestion/following{/other_user}","gists_url":"https://api.github.com/users/lastquestion/gists{/gist_id}","starred_url":"https://api.github.com/users/lastquestion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lastquestion/subscriptions","organizations_url":"https://api.github.com/users/lastquestion/orgs","repos_url":"https://api.github.com/users/lastquestion/repos","events_url":"https://api.github.com/users/lastquestion/events{/privacy}","received_events_url":"https://api.github.com/users/lastquestion/received_events","type":"User","site_admin":false},"repo":{"id":35273307,"name":"PathPicker","full_name":"lastquestion/PathPicker","owner":{"login":"lastquestion","id":1095956,"avatar_url":"https://avatars.githubusercontent.com/u/1095956?v=3","gravatar_id":"","url":"https://api.github.com/users/lastquestion","html_url":"https://github.com/lastquestion","followers_url":"https://api.github.com/users/lastquestion/followers","following_url":"https://api.github.com/users/lastquestion/following{/other_user}","gists_url":"https://api.github.com/users/lastquestion/gists{/gist_id}","starred_url":"https://api.github.com/users/lastquestion/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lastquestion/subscriptions","organizations_url":"https://api.github.com/users/lastquestion/orgs","repos_url":"https://api.github.com/users/lastquestion/repos","events_url":"https://api.github.com/users/lastquestion/events{/privacy}","received_events_url":"https://api.github.com/users/lastquestion/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/lastquestion/PathPicker","description":"PathPicker accepts a wide range of input -- output from git commands, grep results, searches -- pretty much anything.\n\nAfter parsing the input, PathPicker presents you with a nice UI to select which files you're interested in. After that you can open them in your favorite editor or execute arbitrary commands.","fork":true,"url":"https://api.github.com/repos/lastquestion/PathPicker","forks_url":"https://api.github.com/repos/lastquestion/PathPicker/forks","keys_url":"https://api.github.com/repos/lastquestion/PathPicker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lastquestion/PathPicker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lastquestion/PathPicker/teams","hooks_url":"https://api.github.com/repos/lastquestion/PathPicker/hooks","issue_events_url":"https://api.github.com/repos/lastquestion/PathPicker/issues/events{/number}","events_url":"https://api.github.com/repos/lastquestion/PathPicker/events","assignees_url":"https://api.github.com/repos/lastquestion/PathPicker/assignees{/user}","branches_url":"https://api.github.com/repos/lastquestion/PathPicker/branches{/branch}","tags_url":"https://api.github.com/repos/lastquestion/PathPicker/tags","blobs_url":"https://api.github.com/repos/lastquestion/PathPicker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lastquestion/PathPicker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lastquestion/PathPicker/git/refs{/sha}","trees_url":"https://api.github.com/repos/lastquestion/PathPicker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lastquestion/PathPicker/statuses/{sha}","languages_url":"https://api.github.com/repos/lastquestion/PathPicker/languages","stargazers_url":"https://api.github.com/repos/lastquestion/PathPicker/stargazers","contributors_url":"https://api.github.com/repos/lastquestion/PathPicker/contributors","subscribers_url":"https://api.github.com/repos/lastquestion/PathPicker/subscribers","subscription_url":"https://api.github.com/repos/lastquestion/PathPicker/subscription","commits_url":"https://api.github.com/repos/lastquestion/PathPicker/commits{/sha}","git_commits_url":"https://api.github.com/repos/lastquestion/PathPicker/git/commits{/sha}","comments_url":"https://api.github.com/repos/lastquestion/PathPicker/comments{/number}","issue_comment_url":"https://api.github.com/repos/lastquestion/PathPicker/issues/comments{/number}","contents_url":"https://api.github.com/repos/lastquestion/PathPicker/contents/{+path}","compare_url":"https://api.github.com/repos/lastquestion/PathPicker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lastquestion/PathPicker/merges","archive_url":"https://api.github.com/repos/lastquestion/PathPicker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lastquestion/PathPicker/downloads","issues_url":"https://api.github.com/repos/lastquestion/PathPicker/issues{/number}","pulls_url":"https://api.github.com/repos/lastquestion/PathPicker/pulls{/number}","milestones_url":"https://api.github.com/repos/lastquestion/PathPicker/milestones{/number}","notifications_url":"https://api.github.com/repos/lastquestion/PathPicker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lastquestion/PathPicker/labels{/name}","releases_url":"https://api.github.com/repos/lastquestion/PathPicker/releases{/id}","created_at":"2015-05-08T10:27:07Z","updated_at":"2015-05-08T10:27:07Z","pushed_at":"2015-05-10T01:04:32Z","git_url":"git://github.com/lastquestion/PathPicker.git","ssh_url":"git@github.com:lastquestion/PathPicker.git","clone_url":"https://github.com/lastquestion/PathPicker.git","svn_url":"https://github.com/lastquestion/PathPicker","homepage":"http://facebook.github.io/PathPicker/","size":672,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"facebook:master","ref":"master","sha":"b3d9da2a17f403a5dbb3b8da9197e39201da9a42","user":{"login":"facebook","id":69631,"avatar_url":"https://avatars.githubusercontent.com/u/69631?v=3","gravatar_id":"","url":"https://api.github.com/users/facebook","html_url":"https://github.com/facebook","followers_url":"https://api.github.com/users/facebook/followers","following_url":"https://api.github.com/users/facebook/following{/other_user}","gists_url":"https://api.github.com/users/facebook/gists{/gist_id}","starred_url":"https://api.github.com/users/facebook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facebook/subscriptions","organizations_url":"https://api.github.com/users/facebook/orgs","repos_url":"https://api.github.com/users/facebook/repos","events_url":"https://api.github.com/users/facebook/events{/privacy}","received_events_url":"https://api.github.com/users/facebook/received_events","type":"Organization","site_admin":false},"repo":{"id":34887588,"name":"PathPicker","full_name":"facebook/PathPicker","owner":{"login":"facebook","id":69631,"avatar_url":"https://avatars.githubusercontent.com/u/69631?v=3","gravatar_id":"","url":"https://api.github.com/users/facebook","html_url":"https://github.com/facebook","followers_url":"https://api.github.com/users/facebook/followers","following_url":"https://api.github.com/users/facebook/following{/other_user}","gists_url":"https://api.github.com/users/facebook/gists{/gist_id}","starred_url":"https://api.github.com/users/facebook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/facebook/subscriptions","organizations_url":"https://api.github.com/users/facebook/orgs","repos_url":"https://api.github.com/users/facebook/repos","events_url":"https://api.github.com/users/facebook/events{/privacy}","received_events_url":"https://api.github.com/users/facebook/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/facebook/PathPicker","description":"PathPicker accepts a wide range of input -- output from git commands, grep results, searches -- pretty much anything.\n\nAfter parsing the input, PathPicker presents you with a nice UI to select which files you're interested in. After that you can open them in your favorite editor or execute arbitrary commands.","fork":false,"url":"https://api.github.com/repos/facebook/PathPicker","forks_url":"https://api.github.com/repos/facebook/PathPicker/forks","keys_url":"https://api.github.com/repos/facebook/PathPicker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/facebook/PathPicker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/facebook/PathPicker/teams","hooks_url":"https://api.github.com/repos/facebook/PathPicker/hooks","issue_events_url":"https://api.github.com/repos/facebook/PathPicker/issues/events{/number}","events_url":"https://api.github.com/repos/facebook/PathPicker/events","assignees_url":"https://api.github.com/repos/facebook/PathPicker/assignees{/user}","branches_url":"https://api.github.com/repos/facebook/PathPicker/branches{/branch}","tags_url":"https://api.github.com/repos/facebook/PathPicker/tags","blobs_url":"https://api.github.com/repos/facebook/PathPicker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/facebook/PathPicker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/facebook/PathPicker/git/refs{/sha}","trees_url":"https://api.github.com/repos/facebook/PathPicker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/facebook/PathPicker/statuses/{sha}","languages_url":"https://api.github.com/repos/facebook/PathPicker/languages","stargazers_url":"https://api.github.com/repos/facebook/PathPicker/stargazers","contributors_url":"https://api.github.com/repos/facebook/PathPicker/contributors","subscribers_url":"https://api.github.com/repos/facebook/PathPicker/subscribers","subscription_url":"https://api.github.com/repos/facebook/PathPicker/subscription","commits_url":"https://api.github.com/repos/facebook/PathPicker/commits{/sha}","git_commits_url":"https://api.github.com/repos/facebook/PathPicker/git/commits{/sha}","comments_url":"https://api.github.com/repos/facebook/PathPicker/comments{/number}","issue_comment_url":"https://api.github.com/repos/facebook/PathPicker/issues/comments{/number}","contents_url":"https://api.github.com/repos/facebook/PathPicker/contents/{+path}","compare_url":"https://api.github.com/repos/facebook/PathPicker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/facebook/PathPicker/merges","archive_url":"https://api.github.com/repos/facebook/PathPicker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/facebook/PathPicker/downloads","issues_url":"https://api.github.com/repos/facebook/PathPicker/issues{/number}","pulls_url":"https://api.github.com/repos/facebook/PathPicker/pulls{/number}","milestones_url":"https://api.github.com/repos/facebook/PathPicker/milestones{/number}","notifications_url":"https://api.github.com/repos/facebook/PathPicker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/facebook/PathPicker/labels{/name}","releases_url":"https://api.github.com/repos/facebook/PathPicker/releases{/id}","created_at":"2015-05-01T03:05:54Z","updated_at":"2015-05-10T17:04:09Z","pushed_at":"2015-05-10T01:06:29Z","git_url":"git://github.com/facebook/PathPicker.git","ssh_url":"git@github.com:facebook/PathPicker.git","clone_url":"https://github.com/facebook/PathPicker.git","svn_url":"https://github.com/facebook/PathPicker","homepage":"http://facebook.github.io/PathPicker/","size":1447,"stargazers_count":1543,"watchers_count":1543,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":61,"mirror_url":null,"open_issues_count":34,"forks":61,"open_issues":34,"watchers":1543,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/facebook/PathPicker/pulls/53"},"html":{"href":"https://github.com/facebook/PathPicker/pull/53"},"issue":{"href":"https://api.github.com/repos/facebook/PathPicker/issues/53"},"comments":{"href":"https://api.github.com/repos/facebook/PathPicker/issues/53/comments"},"review_comments":{"href":"https://api.github.com/repos/facebook/PathPicker/pulls/53/comments"},"review_comment":{"href":"https://api.github.com/repos/facebook/PathPicker/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/facebook/PathPicker/pulls/53/commits"},"statuses":{"href":"https://api.github.com/repos/facebook/PathPicker/statuses/d6221337bdf0275cf03003f38a82c3c277d303a8"}}}}