Repository: xonsh/xonsh

Issue:
Current session is not included in `history show all`
Output of  `history` (current session) is not included in `history show all`.

```
filo@MSI D:\drive\workspace\example master $ xonfig
+------------------+-----------------+
| xonsh            | 0.4.7           |
| Git SHA          | None            |
| Python           | 3.5.2           |
| PLY              | 3.9             |
| have readline    | True            |
| prompt toolkit   | 1.0.7           |
| shell type       | prompt_toolkit  |
| pygments         | 2.1.3           |
| on posix         | False           |
| on linux         | False           |
| on darwin        | False           |
| on windows       | True            |
| on cygwin        | False           |
| is superuser     | False           |
| default encoding | utf-8           |
| xonsh encoding   | utf-8           |
| encoding errors  | surrogateescape |
+------------------+-----------------+
```



Discussion:
thanks for reporting @chrisfilo! This seems like an easy fix, a PR would be awewome!

So I have been trying to fix this, but haven't been able to get iterate through a `History` object properly.

This is the `_all_xonsh_parser` (slightly modified) which is called for `history show all`

``` python
def _all_xonsh_parser(**kwargs):
    """
    Returns all history as found in XONSH_DATA_DIR.

    return format: (cmd, start_time, index)
    """
    hist = kwargs.get('hist', None)

    data_dir = builtins.__xonsh_env__.get('XONSH_DATA_DIR')
    data_dir = expanduser_abs_path(data_dir)

    files = [os.path.join(data_dir, f) for f in os.listdir(data_dir)
             if f.startswith('xonsh-') and f.endswith('.json')]
    ind = 0
    for f in files:
        try:
            json_file = LazyJSON(f, reopen=False)
        except ValueError:
            # Invalid json file
            pass
        commands = json_file.load()['cmds']
        for c in commands:
            yield (c['inp'].rstrip(), c['ts'][0], ind)
            ind += 1
```

I tried to do something like:

``` python
for h in hist:
    yield h
```

but seems to iterate for a lot longer, not on the number of commands.

I could use some help regarding this!

Hi @SanketDG - it should iterate for the number of commands in each history. I think the mistake is that it should also iterate through the history in the current session.  Something like, 

``` py
for c in builtins.__xonsh_history__.buffer:
     yield (c['inp'].rstrip(), c['ts'][0], ind)
     ind += 1
```

The buffer is the list of commands that have yet to be written to disk and are still in memory.  Thus these are missed.


Resolving patch:
diff --git a/xonsh/history/json.py b/xonsh/history/json.py
--- a/xonsh/history/json.py
+++ b/xonsh/history/json.py
@@ -361,10 +361,8 @@ def flush(self, at_exit=False):
 
     def items(self):
         """Display history items of current session."""
-        ind = 0
         for item, tss in zip(self.inps, self.tss):
-            yield {'inp': item.rstrip(), 'ind': ind, 'ts': tss[0]}
-            ind += 1
+            yield {'inp': item.rstrip(), 'ts': tss[0]}
 
     def all_items(self, **kwargs):
         """
@@ -374,7 +372,6 @@ def all_items(self, **kwargs):
         """
         while self.gc and self.gc.is_alive():
             time.sleep(0.011)  # gc sleeps for 0.01 secs, sleep a beat longer
-        ind = 0
         for f in _xhj_get_history_files():
             try:
                 json_file = xlj.LazyJSON(f, reopen=False)
@@ -383,8 +380,9 @@ def all_items(self, **kwargs):
                 continue
             commands = json_file.load()['cmds']
             for c in commands:
-                yield {'inp': c['inp'].rstrip(), 'ts': c['ts'][0], 'ind': ind}
-                ind += 1
+                yield {'inp': c['inp'].rstrip(), 'ts': c['ts'][0]}
+        # all items should also include session items
+        yield from self.items()
 
     def info(self):
         data = collections.OrderedDict()
diff --git a/xonsh/history/main.py b/xonsh/history/main.py
--- a/xonsh/history/main.py
+++ b/xonsh/history/main.py
@@ -36,9 +36,7 @@ def construct_history(**kwargs):
 
 
 def _xh_session_parser(hist=None, **kwargs):
-    """Returns history items of current session.
-        format: {'inp': cmd, 'ts': start_time, 'ind': index}
-    """
+    """Returns history items of current session."""
     if hist is None:
         hist = builtins.__xonsh_history__
     return hist.items()
@@ -141,7 +139,10 @@ def _xh_get_history(session='session', *, slices=None, datetime_format=None,
     generator
        A filtered list of commands
     """
-    cmds = _XH_HISTORY_SESSIONS[session](location=location)
+    cmds = []
+    for i, item in enumerate(_XH_HISTORY_SESSIONS[session](location=location)):
+        item['ind'] = i
+        cmds.append(item)
     if slices:
         # transform/check all slices
         slices = [xt.ensure_slice(s) for s in slices]
@@ -174,24 +175,22 @@ def _xh_show_history(hist, ns, stdout=None, stderr=None):
         return
     if ns.reverse:
         commands = reversed(list(commands))
-    if not ns.numerate and not ns.timestamp:
+    if ns.numerate and ns.timestamp:
         for c in commands:
-            print(c['inp'], file=stdout)
-    elif not ns.timestamp:
+            dt = datetime.datetime.fromtimestamp(c['ts'])
+            print('{}:({}) {}'.format(c['ind'], xt.format_datetime(dt), c['inp']),
+                  file=stdout)
+    elif ns.numerate:
         for c in commands:
             print('{}: {}'.format(c['ind'], c['inp']), file=stdout)
-    elif not ns.numerate:
+    elif ns.timestamp:
         for c in commands:
             dt = datetime.datetime.fromtimestamp(c['ts'])
             print('({}) {}'.format(xt.format_datetime(dt), c['inp']),
                   file=stdout)
     else:
         for c in commands:
-            dt = datetime.datetime.fromtimestamp(c['ts'])
-            print('{}:({}) {}'.format(c['ind'],
-                                      xt.format_datetime(dt),
-                                      c['inp']),
-                  file=stdout)
+            print(c['inp'], file=stdout)
 
 
 @xla.lazyobject
diff --git a/xonsh/history/sqlite.py b/xonsh/history/sqlite.py
--- a/xonsh/history/sqlite.py
+++ b/xonsh/history/sqlite.py
@@ -210,18 +210,14 @@ def append(self, cmd):
 
     def all_items(self):
         """Display all history items."""
-        i = 0
         for item in xh_sqlite_items(filename=self.filename):
-            yield {'inp': item[0], 'ts': item[1], 'rtn': item[2], 'ind': i}
-            i += 1
+            yield {'inp': item[0], 'ts': item[1], 'rtn': item[2]}
 
     def items(self):
         """Display history items of current session."""
-        i = 0
         for item in xh_sqlite_items(
                 sessionid=str(self.sessionid), filename=self.filename):
-            yield {'inp': item[0], 'ts': item[1], 'rtn': item[2], 'ind': i}
-            i += 1
+            yield {'inp': item[0], 'ts': item[1], 'rtn': item[2]}
 
     def info(self):
         data = collections.OrderedDict()


Test patch:
diff --git a/tests/test_history.py b/tests/test_history.py
--- a/tests/test_history.py
+++ b/tests/test_history.py
@@ -137,8 +137,8 @@ def test_show_cmd_numerate(inp, commands, offset, hist, xonsh_builtins, capsys):
     base_idx, step = offset
     xonsh_builtins.__xonsh_history__ = hist
     xonsh_builtins.__xonsh_env__['HISTCONTROL'] = set()
-    for ts,cmd in enumerate(CMDS):  # populate the shell history
-        hist.append({'inp': cmd, 'rtn': 0, 'ts':(ts+1, ts+1.5)})
+    for ts, cmd in enumerate(CMDS):  # populate the shell history
+        hist.append({'inp': cmd, 'rtn': 0, 'ts':(ts + 1, ts + 1.5)})
 
     exp = ('{}: {}'.format(base_idx + idx * step, cmd)
            for idx, cmd in enumerate(list(commands)))