{"action":"created","comment":{"url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments/29556204","id":29556204,"diff_hunk":"@@ -0,0 +1,312 @@\n+/**\n+ * IO related functions\n+ */\n+\n+module std.experimental.testing.io;\n+\n+import std.concurrency;\n+import std.stdio;\n+import std.conv;\n+\n+\n+/**\n+ * Write if debug output was enabled. Not thread-safe in the sense that it\n+ * will get printed out immediately and may overlap with other output.\n+ * This is why the test runner forces single-threaded mode when debug mode\n+ * is selected.\n+ */\n+void writelnUt(T...)(T args)\n+{\n+    import std.stdio;\n+    if(_debugOutput) writeln(\"    \", args);\n+}\n+\n+private shared(bool) _debugOutput = false; ///print debug msgs?\n+private shared(bool) _forceEscCodes = false; ///use ANSI escape codes anyway?\n+\n+\n+package void enableDebugOutput() nothrow\n+{\n+    synchronized\n+    {\n+        _debugOutput = true;\n+    }\n+}\n+\n+package bool isDebugOutputEnabled() nothrow\n+{\n+    synchronized\n+    {\n+        return _debugOutput;\n+    }\n+}\n+\n+package void forceEscCodes() nothrow\n+{\n+    synchronized\n+    {\n+        _forceEscCodes = true;\n+    }\n+}\n+\n+/**\n+ * Adds to the test cases output so far or immediately prints\n+ */\n+package void addToOutput(ref string output, in string msg) @safe\n+{\n+    if(_debugOutput)\n+    {\n+        import std.stdio;\n+        writeln(msg);\n+    }\n+    else\n+    {\n+        output ~= msg;\n+    }\n+}\n+\n+\n+package void utWrite(T...)(T args)\n+{\n+    WriterThread.get().write(args);\n+}\n+\n+package void utWriteln(T...)(T args)\n+{\n+    WriterThread.get().writeln(args);\n+}\n+\n+package void utWritelnGreen(T...)(T args)\n+{\n+    WriterThread.get().writelnGreen(args);\n+}\n+\n+package void utWritelnRed(T...)(T args)\n+{\n+    WriterThread.get().writelnRed(args);\n+}\n+\n+package void utWriteRed(T...)(T args)\n+{\n+    WriterThread.get().writeRed(args);\n+}\n+\n+package void utWriteYellow(T...)(T args)\n+{\n+    WriterThread.get().writeYellow(args);\n+}\n+\n+\n+/**\n+ * Thread to output to stdout\n+ */\n+class WriterThread\n+{\n+\n+    /**\n+     * Returns a reference to the only instance of this class.\n+     */\n+    static WriterThread get()\n+    {\n+        if(!_instantiated)\n+        {\n+            synchronized\n+            {\n+                if (_instance is null)\n+                {\n+                    _instance = new WriterThread;\n+                }\n+                _instantiated = true;\n+            }\n+        }\n+        return _instance;\n+    }\n+\n+    /**\n+     * Writes the args in a thread-safe manner.\n+     */\n+    void write(T...)(T args)\n+    {\n+        _tid.send(text(args));\n+    }\n+\n+    /**\n+     * Writes the args in a thread-safe manner and appends a newline.\n+     */\n+    void writeln(T...)(T args)\n+    {\n+        write(args, \"\\n\");\n+    }\n+\n+    /**\n+     * Writes the args in a thread-safe manner in green (POSIX only).\n+     * and appends a newline.\n+     */\n+    void writelnGreen(T...)(T args)\n+    {\n+        _tid.send(green(text(args) ~ \"\\n\"));\n+    }\n+\n+    /**\n+     * Writes the args in a thread-safe manner in red (POSIX only)\n+     * and appends a newline.\n+     */\n+    void writelnRed(T...)(T args)\n+    {\n+        _tid.send(red(text(args) ~ \"\\n\"));\n+    }\n+\n+    /**\n+     * Writes the args in a thread-safe manner in red (POSIX only).\n+     * and appends a newline.\n+     */\n+    void writeRed(T...)(T args)\n+    {\n+        _tid.send(red(text(args)));\n+    }\n+\n+    /**\n+     * Writes the args in a thread-safe manner in yellow (POSIX only).\n+     * and appends a newline.\n+     */\n+    void writeYellow(T...)(T args)\n+    {\n+        _tid.send(yellow(text(args)));\n+    }\n+\n+    /**\n+     * Creates the singleton instance and waits until it's ready.\n+     */\n+    static void start()\n+    {\n+        WriterThread.get._tid.send(true, thisTid);\n+        receiveOnly!bool; //wait for it to start\n+    }\n+\n+    /**\n+     * Waits for the writer thread to terminate.\n+     */\n+    void join()\n+    {\n+        _tid.send(thisTid); //tell it to join\n+        receiveOnly!Tid(); //wait for it to join\n+        _instance = null;\n+        _instantiated = false;\n+    }\n+\n+private:\n+\n+    this()\n+    {\n+        _tid = spawn(&threadWriter);\n+        _escCodes = [ \"red\": \"\\033[31;1m\",\n+                      \"green\": \"\\033[32;1m\",\n+                      \"yellow\": \"\\033[33;1m\",\n+                      \"cancel\": \"\\033[0;;m\" ];\n+\n+        version(Posix)\n+        {\n+            import core.sys.posix.unistd;\n+            _useEscCodes = _forceEscCodes || isatty(stdout.fileno()) != 0;\n+        }\n+    }\n+\n+    /**\n+     * Generate green coloured output on POSIX systems\n+     */\n+    string green(in string msg) @safe pure const\n+    {\n+        return escCode(\"green\") ~ msg ~ escCode(\"cancel\");\n+    }\n+\n+    /**\n+     * Generate red coloured output on POSIX systems\n+     */\n+    string red(in string msg) @safe pure const\n+    {\n+        return escCode(\"red\") ~ msg ~ escCode(\"cancel\");\n+    }\n+\n+    /**\n+     * Generate yellow coloured output on POSIX systems\n+     */\n+    string yellow(in string msg) @safe pure const\n+    {\n+        return escCode(\"yellow\") ~ msg ~ escCode(\"cancel\");\n+    }\n+\n+    /**\n+     * Send escape code to the console\n+     */\n+    string escCode(in string code) @safe pure const\n+    {\n+        return _useEscCodes ? _escCodes[code] : \"\";\n+    }","path":"std/experimental/testing/io.d","position":null,"original_position":244,"commit_id":"30c39fdd2a5a7d17dd0b4683b3643b144512002f","original_commit_id":"8f136b08cf7c76ccd9fc07eb0d6d3d28ce9afbd9","user":{"login":"burner","id":13327,"avatar_url":"https://avatars.githubusercontent.com/u/13327?v=3","gravatar_id":"","url":"https://api.github.com/users/burner","html_url":"https://github.com/burner","followers_url":"https://api.github.com/users/burner/followers","following_url":"https://api.github.com/users/burner/following{/other_user}","gists_url":"https://api.github.com/users/burner/gists{/gist_id}","starred_url":"https://api.github.com/users/burner/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/burner/subscriptions","organizations_url":"https://api.github.com/users/burner/orgs","repos_url":"https://api.github.com/users/burner/repos","events_url":"https://api.github.com/users/burner/events{/privacy}","received_events_url":"https://api.github.com/users/burner/received_events","type":"User","site_admin":false},"body":"commented to the wrong line! \"yellow\" and friends should be static as there is no way for the user AFAIK to change _escCodes","created_at":"2015-05-03T13:44:49Z","updated_at":"2015-05-03T13:44:49Z","html_url":"https://github.com/D-Programming-Language/phobos/pull/3207#discussion_r29556204","pull_request_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207","_links":{"self":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments/29556204"},"html":{"href":"https://github.com/D-Programming-Language/phobos/pull/3207#discussion_r29556204"},"pull_request":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207"}}},"pull_request":{"url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207","id":33665023,"html_url":"https://github.com/D-Programming-Language/phobos/pull/3207","diff_url":"https://github.com/D-Programming-Language/phobos/pull/3207.diff","patch_url":"https://github.com/D-Programming-Language/phobos/pull/3207.patch","issue_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3207","number":3207,"state":"open","locked":false,"title":"Introducing std.experimental.testing","user":{"login":"atilaneves","id":4956425,"avatar_url":"https://avatars.githubusercontent.com/u/4956425?v=3","gravatar_id":"","url":"https://api.github.com/users/atilaneves","html_url":"https://github.com/atilaneves","followers_url":"https://api.github.com/users/atilaneves/followers","following_url":"https://api.github.com/users/atilaneves/following{/other_user}","gists_url":"https://api.github.com/users/atilaneves/gists{/gist_id}","starred_url":"https://api.github.com/users/atilaneves/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/atilaneves/subscriptions","organizations_url":"https://api.github.com/users/atilaneves/orgs","repos_url":"https://api.github.com/users/atilaneves/repos","events_url":"https://api.github.com/users/atilaneves/events{/privacy}","received_events_url":"https://api.github.com/users/atilaneves/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-04-20T13:28:00Z","updated_at":"2015-05-03T13:44:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6cb33d19a5ced203d9be5e968c31125a637d04da","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207/commits","review_comments_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207/comments","review_comment_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments{/number}","comments_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3207/comments","statuses_url":"https://api.github.com/repos/D-Programming-Language/phobos/statuses/30c39fdd2a5a7d17dd0b4683b3643b144512002f","head":{"label":"atilaneves:testing_pr","ref":"testing_pr","sha":"30c39fdd2a5a7d17dd0b4683b3643b144512002f","user":{"login":"atilaneves","id":4956425,"avatar_url":"https://avatars.githubusercontent.com/u/4956425?v=3","gravatar_id":"","url":"https://api.github.com/users/atilaneves","html_url":"https://github.com/atilaneves","followers_url":"https://api.github.com/users/atilaneves/followers","following_url":"https://api.github.com/users/atilaneves/following{/other_user}","gists_url":"https://api.github.com/users/atilaneves/gists{/gist_id}","starred_url":"https://api.github.com/users/atilaneves/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/atilaneves/subscriptions","organizations_url":"https://api.github.com/users/atilaneves/orgs","repos_url":"https://api.github.com/users/atilaneves/repos","events_url":"https://api.github.com/users/atilaneves/events{/privacy}","received_events_url":"https://api.github.com/users/atilaneves/received_events","type":"User","site_admin":false},"repo":{"id":33829573,"name":"phobos","full_name":"atilaneves/phobos","owner":{"login":"atilaneves","id":4956425,"avatar_url":"https://avatars.githubusercontent.com/u/4956425?v=3","gravatar_id":"","url":"https://api.github.com/users/atilaneves","html_url":"https://github.com/atilaneves","followers_url":"https://api.github.com/users/atilaneves/followers","following_url":"https://api.github.com/users/atilaneves/following{/other_user}","gists_url":"https://api.github.com/users/atilaneves/gists{/gist_id}","starred_url":"https://api.github.com/users/atilaneves/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/atilaneves/subscriptions","organizations_url":"https://api.github.com/users/atilaneves/orgs","repos_url":"https://api.github.com/users/atilaneves/repos","events_url":"https://api.github.com/users/atilaneves/events{/privacy}","received_events_url":"https://api.github.com/users/atilaneves/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/atilaneves/phobos","description":"The standard library of the D programming language","fork":true,"url":"https://api.github.com/repos/atilaneves/phobos","forks_url":"https://api.github.com/repos/atilaneves/phobos/forks","keys_url":"https://api.github.com/repos/atilaneves/phobos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/atilaneves/phobos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/atilaneves/phobos/teams","hooks_url":"https://api.github.com/repos/atilaneves/phobos/hooks","issue_events_url":"https://api.github.com/repos/atilaneves/phobos/issues/events{/number}","events_url":"https://api.github.com/repos/atilaneves/phobos/events","assignees_url":"https://api.github.com/repos/atilaneves/phobos/assignees{/user}","branches_url":"https://api.github.com/repos/atilaneves/phobos/branches{/branch}","tags_url":"https://api.github.com/repos/atilaneves/phobos/tags","blobs_url":"https://api.github.com/repos/atilaneves/phobos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/atilaneves/phobos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/atilaneves/phobos/git/refs{/sha}","trees_url":"https://api.github.com/repos/atilaneves/phobos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/atilaneves/phobos/statuses/{sha}","languages_url":"https://api.github.com/repos/atilaneves/phobos/languages","stargazers_url":"https://api.github.com/repos/atilaneves/phobos/stargazers","contributors_url":"https://api.github.com/repos/atilaneves/phobos/contributors","subscribers_url":"https://api.github.com/repos/atilaneves/phobos/subscribers","subscription_url":"https://api.github.com/repos/atilaneves/phobos/subscription","commits_url":"https://api.github.com/repos/atilaneves/phobos/commits{/sha}","git_commits_url":"https://api.github.com/repos/atilaneves/phobos/git/commits{/sha}","comments_url":"https://api.github.com/repos/atilaneves/phobos/comments{/number}","issue_comment_url":"https://api.github.com/repos/atilaneves/phobos/issues/comments{/number}","contents_url":"https://api.github.com/repos/atilaneves/phobos/contents/{+path}","compare_url":"https://api.github.com/repos/atilaneves/phobos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/atilaneves/phobos/merges","archive_url":"https://api.github.com/repos/atilaneves/phobos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/atilaneves/phobos/downloads","issues_url":"https://api.github.com/repos/atilaneves/phobos/issues{/number}","pulls_url":"https://api.github.com/repos/atilaneves/phobos/pulls{/number}","milestones_url":"https://api.github.com/repos/atilaneves/phobos/milestones{/number}","notifications_url":"https://api.github.com/repos/atilaneves/phobos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/atilaneves/phobos/labels{/name}","releases_url":"https://api.github.com/repos/atilaneves/phobos/releases{/id}","created_at":"2015-04-12T19:03:01Z","updated_at":"2015-04-12T19:03:04Z","pushed_at":"2015-04-30T20:03:44Z","git_url":"git://github.com/atilaneves/phobos.git","ssh_url":"git@github.com:atilaneves/phobos.git","clone_url":"https://github.com/atilaneves/phobos.git","svn_url":"https://github.com/atilaneves/phobos","homepage":"dlang.org/phobos","size":39440,"stargazers_count":0,"watchers_count":0,"language":"D","has_issues":false,"has_downloads":true,"has_wiki":false,"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":"D-Programming-Language:master","ref":"master","sha":"41d1162619039e8e535060b920ff54cc2c44ebbb","user":{"login":"D-Programming-Language","id":565913,"avatar_url":"https://avatars.githubusercontent.com/u/565913?v=3","gravatar_id":"","url":"https://api.github.com/users/D-Programming-Language","html_url":"https://github.com/D-Programming-Language","followers_url":"https://api.github.com/users/D-Programming-Language/followers","following_url":"https://api.github.com/users/D-Programming-Language/following{/other_user}","gists_url":"https://api.github.com/users/D-Programming-Language/gists{/gist_id}","starred_url":"https://api.github.com/users/D-Programming-Language/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/D-Programming-Language/subscriptions","organizations_url":"https://api.github.com/users/D-Programming-Language/orgs","repos_url":"https://api.github.com/users/D-Programming-Language/repos","events_url":"https://api.github.com/users/D-Programming-Language/events{/privacy}","received_events_url":"https://api.github.com/users/D-Programming-Language/received_events","type":"Organization","site_admin":false},"repo":{"id":1257084,"name":"phobos","full_name":"D-Programming-Language/phobos","owner":{"login":"D-Programming-Language","id":565913,"avatar_url":"https://avatars.githubusercontent.com/u/565913?v=3","gravatar_id":"","url":"https://api.github.com/users/D-Programming-Language","html_url":"https://github.com/D-Programming-Language","followers_url":"https://api.github.com/users/D-Programming-Language/followers","following_url":"https://api.github.com/users/D-Programming-Language/following{/other_user}","gists_url":"https://api.github.com/users/D-Programming-Language/gists{/gist_id}","starred_url":"https://api.github.com/users/D-Programming-Language/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/D-Programming-Language/subscriptions","organizations_url":"https://api.github.com/users/D-Programming-Language/orgs","repos_url":"https://api.github.com/users/D-Programming-Language/repos","events_url":"https://api.github.com/users/D-Programming-Language/events{/privacy}","received_events_url":"https://api.github.com/users/D-Programming-Language/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/D-Programming-Language/phobos","description":"The standard library of the D programming language","fork":false,"url":"https://api.github.com/repos/D-Programming-Language/phobos","forks_url":"https://api.github.com/repos/D-Programming-Language/phobos/forks","keys_url":"https://api.github.com/repos/D-Programming-Language/phobos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/D-Programming-Language/phobos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/D-Programming-Language/phobos/teams","hooks_url":"https://api.github.com/repos/D-Programming-Language/phobos/hooks","issue_events_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/events{/number}","events_url":"https://api.github.com/repos/D-Programming-Language/phobos/events","assignees_url":"https://api.github.com/repos/D-Programming-Language/phobos/assignees{/user}","branches_url":"https://api.github.com/repos/D-Programming-Language/phobos/branches{/branch}","tags_url":"https://api.github.com/repos/D-Programming-Language/phobos/tags","blobs_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/refs{/sha}","trees_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/D-Programming-Language/phobos/statuses/{sha}","languages_url":"https://api.github.com/repos/D-Programming-Language/phobos/languages","stargazers_url":"https://api.github.com/repos/D-Programming-Language/phobos/stargazers","contributors_url":"https://api.github.com/repos/D-Programming-Language/phobos/contributors","subscribers_url":"https://api.github.com/repos/D-Programming-Language/phobos/subscribers","subscription_url":"https://api.github.com/repos/D-Programming-Language/phobos/subscription","commits_url":"https://api.github.com/repos/D-Programming-Language/phobos/commits{/sha}","git_commits_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/commits{/sha}","comments_url":"https://api.github.com/repos/D-Programming-Language/phobos/comments{/number}","issue_comment_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/comments{/number}","contents_url":"https://api.github.com/repos/D-Programming-Language/phobos/contents/{+path}","compare_url":"https://api.github.com/repos/D-Programming-Language/phobos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/D-Programming-Language/phobos/merges","archive_url":"https://api.github.com/repos/D-Programming-Language/phobos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/D-Programming-Language/phobos/downloads","issues_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues{/number}","pulls_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls{/number}","milestones_url":"https://api.github.com/repos/D-Programming-Language/phobos/milestones{/number}","notifications_url":"https://api.github.com/repos/D-Programming-Language/phobos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/D-Programming-Language/phobos/labels{/name}","releases_url":"https://api.github.com/repos/D-Programming-Language/phobos/releases{/id}","created_at":"2011-01-15T07:00:06Z","updated_at":"2015-05-02T21:27:51Z","pushed_at":"2015-05-03T13:44:25Z","git_url":"git://github.com/D-Programming-Language/phobos.git","ssh_url":"git@github.com:D-Programming-Language/phobos.git","clone_url":"https://github.com/D-Programming-Language/phobos.git","svn_url":"https://github.com/D-Programming-Language/phobos","homepage":"dlang.org/phobos","size":75006,"stargazers_count":591,"watchers_count":591,"language":"D","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":401,"mirror_url":null,"open_issues_count":71,"forks":401,"open_issues":71,"watchers":591,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207"},"html":{"href":"https://github.com/D-Programming-Language/phobos/pull/3207"},"issue":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3207"},"comments":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3207/comments"},"review_comments":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207/comments"},"review_comment":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3207/commits"},"statuses":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/statuses/30c39fdd2a5a7d17dd0b4683b3643b144512002f"}}}}