{"action":"created","issue":{"url":"https://api.github.com/repos/xonsh/xonsh/issues/2049","repository_url":"https://api.github.com/repos/xonsh/xonsh","labels_url":"https://api.github.com/repos/xonsh/xonsh/issues/2049/labels{/name}","comments_url":"https://api.github.com/repos/xonsh/xonsh/issues/2049/comments","events_url":"https://api.github.com/repos/xonsh/xonsh/issues/2049/events","html_url":"https://github.com/xonsh/xonsh/issues/2049","id":198395600,"number":2049,"title":"tty attrs change when executing a command which catch the tty and the prediction fails","user":{"login":"jb-leger","id":24868098,"avatar_url":"https://avatars.githubusercontent.com/u/24868098?v=3","gravatar_id":"","url":"https://api.github.com/users/jb-leger","html_url":"https://github.com/jb-leger","followers_url":"https://api.github.com/users/jb-leger/followers","following_url":"https://api.github.com/users/jb-leger/following{/other_user}","gists_url":"https://api.github.com/users/jb-leger/gists{/gist_id}","starred_url":"https://api.github.com/users/jb-leger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jb-leger/subscriptions","organizations_url":"https://api.github.com/users/jb-leger/orgs","repos_url":"https://api.github.com/users/jb-leger/repos","events_url":"https://api.github.com/users/jb-leger/events{/privacy}","received_events_url":"https://api.github.com/users/jb-leger/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2017-01-03T00:46:02Z","updated_at":"2017-01-13T19:52:16Z","closed_at":null,"body":"Hi everybody,\r\n\r\nI have a bug which blocks my usage, when I use a program which use the tty directly, _e.g._ `git commit -p` which call `vim` at the end. For the first commit it's works fine, for the second, when I need to enter something I have troubles.\r\n\r\n```\r\njben@germinale ~/falsegit master $ git commit -p\r\n[...git stuff with vim...]\r\njben@germinale ~/falsegit master $ git commit -p\r\ndiff --git a/truc b/truc\r\n[...a diff...]\r\nStage this hunk [y,n,q,a,d,/,e,?]? y^M^M^M^M^M^M^M^M^M\r\n```\r\n\r\nIn fact, when I look the source code, some command are handled differently, in `xonsh/built-ins.py`:\r\n```python\r\ndef _update_last_spec(last):\r\n[...]\r\n    if callable_alias:\r\n        pass\r\n    else:\r\n        thable = builtins.__xonsh_commands_cache__.predict_threadable(last.args)\r\n        if captured and thable:\r\n            last.cls = PopenThread\r\n        elif not thable:\r\n            # foreground processes should use Popen and not pipe stdout, stderr\r\n            last.threadable = False\r\n            return\r\n    [...]\r\n```\r\n\r\nWe see that we try to predict if a command is threadable, this is done in `xonsh/commands_cache.py` with predictor, from a default value:\r\n\r\n```python\r\ndef default_threadable_predictors():\r\n    \"\"\"Generates a new defaultdict for known threadable predictors.\r\n    The default is to predict true.\r\n    \"\"\"\r\n    # alphabetical, for what it is worth.\r\n    predictors = {\r\n        'bash': predict_shell,\r\n        'csh': predict_shell,\r\n        'clear': predict_false,\r\n         [...]\r\n```\r\n\r\nThis explain that we do not have this behavior with some commands, but with other.\r\n\r\nBut, I do _not_ think adding `git` here is a good idea, and I have a lot of home made script which call vim or which use directly the tty, so I investigate to found what's happening.\r\n\r\nAs far as I understand, when the prediction is incorrect, and a catching tty program is launch when `xonsh` did not predict that, the program change directly the attributes of the tty, as you can see:\r\n\r\n```\r\njben@germinale ~/falsegit master $ import sys,termios\r\njben@germinale ~/falsegit master $ termios.tcgetattr(sys.stdin.fileno())[0:-1]\r\n[17664, 5, 191, 35387, 15, 15]\r\njben@germinale ~/falsegit master $ git commit -p\r\n[...git stuff with vim...]\r\njben@germinale ~/falsegit master $ termios.tcgetattr(sys.stdin.fileno())[0:-1]\r\n[17408, 1, 191, 2602, 15, 15]\r\n```\r\n\r\nSo I think, to cover the case of incorrect predictions, each time a command is finished, `xonsh` should be check the pty attributes have not changed, and in this case set it again to the right value.\r\n\r\nIf I do so, it works well.\r\n\r\n```\r\njben@germinale ~/falsegit master $ import sys,termios\r\njben@germinale ~/falsegit master $ attrs = termios.tcgetattr(sys.stdin.fileno())\r\njben@germinale ~/falsegit master $ git commit -p\r\n[...git stuff with vim...]\r\njben@germinale ~/falsegit master $ termios.tcsetattr(sys.stdin.fileno(),termios.TCSADRAIN,attrs)\r\njben@germinale ~/falsegit master $ git commit -p\r\n[...it works well now...]\r\n```\r\n\r\nI do not know where to do that stuff nicely in the architecture of `xonsh`. For me I use only a dirty quick fix with notification in my prompt, in my `.xonshrc` I added:\r\n\r\n```python\r\n$STDIN_ATTRS = termios.tcgetattr(sys.stdin.fileno())\r\ndef dirty_quick_fix():\r\n    new_attrs = termios.tcgetattr(sys.stdin.fileno())\r\n    if new_attrs[0:-1] == $STDIN_ATTRS[0:-1]:\r\n        return None\r\n    termios.tcsetattr(sys.stdin.fileno(),termios.TCSADRAIN,$STDIN_ATTRS)\r\n    return \"[dirty quick fix applied]\"\r\n$PROMPT_FIELDS['dirty_quick_fix'] = dirty_quick_fix\r\n$PROMPT = $PROMPT.replace('{prompt_end}','{BOLD_RED}{dirty_quick_fix:{} }{prompt_end}')\r\n```\r\n\r\nAnd now, I can use my `xonsh` without this bug:\r\n```\r\njben@germinale ~/falsegit master $ grep bonjour /tmp/truc #command which do not catch tty\r\njben@germinale ~/falsegit master $ #ok all is good, nothing done\r\njben@germinale ~/falsegit master $ git commit -p\r\n[...git stuff with vim...]\r\njben@germinale ~/falsegit master [dirty quick fix applied] $ #tty attrs were restored\r\n```\r\n\r\nI hope this stuff helps you to fix this bug."},"comment":{"url":"https://api.github.com/repos/xonsh/xonsh/issues/comments/272531471","html_url":"https://github.com/xonsh/xonsh/issues/2049#issuecomment-272531471","issue_url":"https://api.github.com/repos/xonsh/xonsh/issues/2049","id":272531471,"user":{"login":"jb-leger","id":24868098,"avatar_url":"https://avatars.githubusercontent.com/u/24868098?v=3","gravatar_id":"","url":"https://api.github.com/users/jb-leger","html_url":"https://github.com/jb-leger","followers_url":"https://api.github.com/users/jb-leger/followers","following_url":"https://api.github.com/users/jb-leger/following{/other_user}","gists_url":"https://api.github.com/users/jb-leger/gists{/gist_id}","starred_url":"https://api.github.com/users/jb-leger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jb-leger/subscriptions","organizations_url":"https://api.github.com/users/jb-leger/orgs","repos_url":"https://api.github.com/users/jb-leger/repos","events_url":"https://api.github.com/users/jb-leger/events{/privacy}","received_events_url":"https://api.github.com/users/jb-leger/received_events","type":"User","site_admin":false},"created_at":"2017-01-13T19:52:16Z","updated_at":"2017-01-13T19:52:16Z","body":"The issue is still present when the predictor fails. But now, most of the time, the predictor do the job. I am preparing a PR for this case, we do not need to keep this issue open, we will continue the discussion in the PR. "}}
{"actor":{"display_login":"jb-leger"}}