#534: Improve open rule
diff --git a/README.md b/README.md
index 395253f4a..29d73ff13 100644
--- a/README.md
+++ b/README.md
@@ -202,7 +202,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
 * `npm_wrong_command` &ndash; fixes wrong npm commands like `npm urgrade`;
 * `no_command` &ndash; fixes wrong console commands, for example `vom/vim`;
 * `no_such_file` &ndash; creates missing directories with `mv` and `cp` commands;
-* `open` &ndash; prepends `http` to address passed to `open`;
+* `open` &ndash; either prepends `http://` to address passed to `open` or create a new file or directory and passes it to `open`;
 * `pip_unknown_command` &ndash; fixes wrong `pip` commands, for example `pip instatl/pip install`;
 * `python_command` &ndash; prepends `python` when you trying to run not executable/without `./` python script;
 * `python_execute` &ndash; appends missing `.py` when executing Python files;
diff --git a/tests/rules/test_open.py b/tests/rules/test_open.py
index c80eeca8b..9186adf45 100644
--- a/tests/rules/test_open.py
+++ b/tests/rules/test_open.py
@@ -1,31 +1,49 @@
 import pytest
-from thefuck.rules.open import match, get_new_command
+from thefuck.rules.open import is_arg_url, match, get_new_command
 from tests.utils import Command
 
 
-@pytest.mark.parametrize('command', [
-    Command(script='open foo.com'),
-    Command(script='open foo.ly'),
-    Command(script='open foo.org'),
-    Command(script='open foo.net'),
-    Command(script='open foo.se'),
-    Command(script='open foo.io'),
-    Command(script='xdg-open foo.com'),
-    Command(script='gnome-open foo.com'),
-    Command(script='kde-open foo.com')])
-def test_match(command):
-    assert match(command)
-
-
-@pytest.mark.parametrize('command, new_command', [
-    (Command('open foo.com'), 'open http://foo.com'),
-    (Command('open foo.ly'), 'open http://foo.ly'),
-    (Command('open foo.org'), 'open http://foo.org'),
-    (Command('open foo.net'), 'open http://foo.net'),
-    (Command('open foo.se'), 'open http://foo.se'),
-    (Command('open foo.io'), 'open http://foo.io'),
-    (Command('xdg-open foo.io'), 'xdg-open http://foo.io'),
-    (Command('gnome-open foo.io'), 'gnome-open http://foo.io'),
-    (Command('kde-open foo.io'), 'kde-open http://foo.io')])
-def test_get_new_command(command, new_command):
-    assert get_new_command(command) == new_command
+@pytest.fixture
+def stderr(script):
+    return 'The file {} does not exist.\n'.format(script.split(' ', 1)[1])
+
+
+@pytest.mark.parametrize('script', [
+    'open foo.com',
+    'open foo.edu',
+    'open foo.info',
+    'open foo.io',
+    'open foo.ly',
+    'open foo.me',
+    'open foo.net',
+    'open foo.org',
+    'open foo.se',
+    'open www.foo.ru'])
+def test_is_arg_url(script):
+    assert is_arg_url(Command(script))
+
+
+@pytest.mark.parametrize('script', ['open foo', 'open bar.txt', 'open egg.doc'])
+def test_not_is_arg_url(script):
+    assert not is_arg_url(Command(script))
+
+
+@pytest.mark.parametrize('script', [
+    'open foo.com',
+    'xdg-open foo.com',
+    'gnome-open foo.com',
+    'kde-open foo.com',
+    'open nonest'])
+def test_match(script, stderr):
+    assert match(Command(script, stderr=stderr))
+
+
+@pytest.mark.parametrize('script, new_command', [
+    ('open foo.io', ['open http://foo.io']),
+    ('xdg-open foo.io', ['xdg-open http://foo.io']),
+    ('gnome-open foo.io', ['gnome-open http://foo.io']),
+    ('kde-open foo.io', ['kde-open http://foo.io']),
+    ('open nonest', ['touch nonest && open nonest',
+                     'mkdir nonest && open nonest'])])
+def test_get_new_command(script, new_command, stderr):
+    assert get_new_command(Command(script, stderr=stderr)) == new_command
diff --git a/thefuck/rules/open.py b/thefuck/rules/open.py
index b46f497d7..86f200879 100644
--- a/thefuck/rules/open.py
+++ b/thefuck/rules/open.py
@@ -5,22 +5,36 @@
 # The file ~/github.com does not exist.
 # Perhaps you meant 'http://github.com'?
 #
-from thefuck.utils import for_app
+from thefuck.shells import shell
+from thefuck.utils import eager, for_app
+
+
+def is_arg_url(command):
+    return ('.com' in command.script or
+            '.edu' in command.script or
+            '.info' in command.script or
+            '.io' in command.script or
+            '.ly' in command.script or
+            '.me' in command.script or
+            '.net' in command.script or
+            '.org' in command.script or
+            '.se' in command.script or
+            'www.' in command.script)
 
 
 @for_app('open', 'xdg-open', 'gnome-open', 'kde-open')
 def match(command):
-    return ('.com' in command.script
-            or '.net' in command.script
-            or '.org' in command.script
-            or '.ly' in command.script
-            or '.io' in command.script
-            or '.se' in command.script
-            or '.edu' in command.script
-            or '.info' in command.script
-            or '.me' in command.script
-            or 'www.' in command.script)
+    return (is_arg_url(command) or
+            command.stderr.strip().startswith('The file ') and
+            command.stderr.strip().endswith(' does not exist.'))
 
 
+@eager
 def get_new_command(command):
-    return command.script.replace('open ', 'open http://')
+    stderr = command.stderr.strip()
+    if is_arg_url(command):
+        yield command.script.replace('open ', 'open http://')
+    elif stderr.startswith('The file ') and stderr.endswith(' does not exist.'):
+        arg = command.script.split(' ', 1)[1]
+        for option in ['touch', 'mkdir']:
+            yield shell.and_(u'{} {}'.format(option, arg), command.script)

This change improves the `open` rule and its tests and implement one of the features suggested by @mlk on #534.
