mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 08:24:40 +01:00
Merge branch 'master' into is3474
This commit is contained in:
commit
65e639eb88
24 changed files with 339 additions and 207 deletions
|
@ -1,4 +1,4 @@
|
|||
version: 0.9.14.{build}
|
||||
version: 0.9.15.{build}
|
||||
os: Windows Server 2012 R2
|
||||
environment:
|
||||
|
||||
|
|
37
.authors.yml
37
.authors.yml
|
@ -68,7 +68,7 @@
|
|||
github: gforsyth
|
||||
- name: Morten Enemark Lund
|
||||
email: melund@gmail.com
|
||||
num_commits: 486
|
||||
num_commits: 490
|
||||
first_commit: 2015-07-10 07:54:10
|
||||
github: melund
|
||||
- name: Ned Letcher
|
||||
|
@ -384,7 +384,7 @@
|
|||
email: lalochcz@gmail.com
|
||||
aliases:
|
||||
- laloch
|
||||
num_commits: 43
|
||||
num_commits: 47
|
||||
first_commit: 2018-07-26 13:51:50
|
||||
github: laloch
|
||||
- name: Nico Lehmann
|
||||
|
@ -434,7 +434,7 @@
|
|||
github: funkyfuture
|
||||
- name: Anthony Scopatz
|
||||
email: scopatz@gmail.com
|
||||
num_commits: 2587
|
||||
num_commits: 2593
|
||||
first_commit: 2015-01-21 17:04:13
|
||||
github: scopatz
|
||||
- name: anatoly techtonik
|
||||
|
@ -1016,7 +1016,7 @@
|
|||
first_commit: 2018-09-16 22:50:24
|
||||
- name: Gyuri Horak
|
||||
email: dyuri@horak.hu
|
||||
num_commits: 1
|
||||
num_commits: 2
|
||||
first_commit: 2019-06-18 12:00:16
|
||||
github: dyuri
|
||||
- name: Ke Zhang
|
||||
|
@ -1092,12 +1092,14 @@
|
|||
email: drmikecrowe@gmail.com
|
||||
aliases:
|
||||
- drmikecrowe
|
||||
num_commits: 1
|
||||
num_commits: 6
|
||||
first_commit: 2020-01-28 09:44:58
|
||||
github: drmikecrowe
|
||||
- name: anki-code
|
||||
email: anki-code@users.noreply.github.com
|
||||
num_commits: 14
|
||||
alternate_emails:
|
||||
- anki-code
|
||||
num_commits: 21
|
||||
first_commit: 2019-10-15 18:20:58
|
||||
- name: Sylvain Corlay
|
||||
email: sylvain.corlay@gmail.com
|
||||
|
@ -1118,3 +1120,26 @@
|
|||
num_commits: 1
|
||||
first_commit: 2020-02-05 13:38:52
|
||||
github: marciomazza
|
||||
- name: Noortheen Raja
|
||||
email: jnoortheen@gmail.com
|
||||
num_commits: 2
|
||||
first_commit: 2020-03-15 10:13:56
|
||||
github: jnoortheen
|
||||
- name: Samuel Lotz
|
||||
email: samuel.lotz@salotz.info
|
||||
num_commits: 3
|
||||
first_commit: 2020-03-03 11:30:33
|
||||
github: salotz
|
||||
- name: Jerzy Drozdz
|
||||
email: jerzy.drozdz@gmail.com
|
||||
num_commits: 1
|
||||
first_commit: 2020-03-01 11:56:23
|
||||
- name: Gabriel Vogel
|
||||
email: gabriel.vogel@online.de
|
||||
num_commits: 2
|
||||
first_commit: 2020-03-10 19:06:59
|
||||
github: Gobbel2000
|
||||
- name: anki
|
||||
email: anki@code.email
|
||||
num_commits: 2
|
||||
first_commit: 2020-03-02 04:59:17
|
||||
|
|
13
.mailmap
13
.mailmap
|
@ -27,8 +27,8 @@ Jean-Benoist Leger <jb@leger.tf> Jean-Benoist Leger <jbleger@gertrude>
|
|||
Jean-Benoist Leger <jb@leger.tf> Jean-Benoist Leger <jbleger@hds.utc.fr>
|
||||
christopher <cjwright4242@gmail.com>
|
||||
Klaus Alexander Seistrup <klaus@seistrup.dk> Klaus Alexander Seistrup <kseistrup@users.noreply.github.com>
|
||||
Leonardo Santagada <santagada@gmail.com>
|
||||
David Strobach <lalochcz@gmail.com> laloch <lalochcz@gmail.com>
|
||||
Leonardo Santagada <santagada@gmail.com>
|
||||
Burak Yiğit Kaya <ben@byk.im> Burak Yigit Kaya <ben@byk.im>
|
||||
Aaron Griffin <aig787@gmail.com>
|
||||
Rob Brewer <rwb123@gmail.com> Robert W. Brewer <rwb123@gmail.com>
|
||||
|
@ -40,6 +40,7 @@ Guillaume Leclerc <guillaume.leclerc@epfl.ch> Guillaume Leclerc <guillaume.lecle
|
|||
Gordon Ball <gordon@chronitis.net>
|
||||
Travis Shirk <travis@pobox.com>
|
||||
Joel Gerber <joel@grrbrr.ca>
|
||||
anki-code <anki-code@users.noreply.github.com> anki-code <anki-code>
|
||||
vaaaaanquish <6syun9@gmail.com> @vaaaaanquish <6syun9@gmail.com>
|
||||
vaaaaanquish <6syun9@gmail.com> vaaaaanquish <6syun9@gmail.com>
|
||||
vaaaaanquish <6syun9@gmail.com> 6syun9 <6syun9@gmail.com>
|
||||
|
@ -53,7 +54,6 @@ Carmen Bianca Bakker <carmen@carmenbianca.eu>
|
|||
Frank Sachsenheim <funkyfuture@riseup.net> Frank Sachsenheim <funkyfuture@users.noreply.github.com>
|
||||
Kurtis Rader <krader@skepticism.us>
|
||||
cryzed <cryzed@googlemail.com>
|
||||
anki-code <anki-code@users.noreply.github.com>
|
||||
Brian Visel <eode@eptitude.net>
|
||||
Andrew Hundt <ATHundt@gmail.com>
|
||||
Jonathan Slenders <jonathan@slenders.be>
|
||||
|
@ -82,6 +82,7 @@ Raphael Gaschignard <raphael@rtpg.co>
|
|||
Nathan Goldbaum <ngoldbau@illinois.edu> Nathan Goldbaum <goldbaum@ucolick.org>
|
||||
mel <mel@anybodytech.com>
|
||||
Jared Crawford <jmcrawford45@gmail.com>
|
||||
Mike Crowe <drmikecrowe@gmail.com> drmikecrowe <drmikecrowe@gmail.com>
|
||||
JuanPablo <jpabloaj@gmail.com>
|
||||
Ollie Terrance <ollie.terrance@live.co.uk>
|
||||
Marcel Bollmann <bollmann@linguistics.rub.de>
|
||||
|
@ -139,6 +140,7 @@ Niklas Hambüchen <mail@nh2.me>
|
|||
Sébastien Pierre <sebastien.pierre@gmail.com>
|
||||
shadow-light <42055707+shadow-light@users.noreply.github.com>
|
||||
Jan Chren <dev.rindeal@gmail.com>
|
||||
Samuel Lotz <samuel.lotz@salotz.info>
|
||||
Mark Wiebe <mwwiebe@gmail.com>
|
||||
Nathan Hoad <nathan@getoffmalawn.com>
|
||||
Eric Dill <edill@bnl.gov>
|
||||
|
@ -161,11 +163,15 @@ Owen Campbell <owen.campbell@tanti.org.uk>
|
|||
Steven Kryskalla <skryskalla@gmail.com>
|
||||
cclauss <cclauss@me.com>
|
||||
Eddie Peters <edward.paul.peters@gmail.com>
|
||||
Gyuri Horak <dyuri@horak.hu>
|
||||
Ke Zhang <kezhang@bnl.gov> ke-zhang-rd <kezhang@bnl.gov>
|
||||
László Vaskó <vlaci@balabit.hu>
|
||||
Allan Crooks <allan.crooks@sixtyten.org>
|
||||
micimize <rosenthalm93@gmail.com>
|
||||
Edmund Miller <edmund.a.miller@protonmail.com>
|
||||
Noortheen Raja <jnoortheen@gmail.com>
|
||||
Gabriel Vogel <gabriel.vogel@online.de>
|
||||
anki <anki@code.email>
|
||||
Dan Allan <dallan@bnl.gov>
|
||||
Ned Letcher <nletcher@gmail.com>
|
||||
Zach Crownover <zachary.crownover@gmail.com>
|
||||
|
@ -222,16 +228,15 @@ stonebig <stonebig34@gmail.com>
|
|||
Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
|
||||
Troy de Freitas <9503857+ntdef@users.noreply.github.com>
|
||||
Rodrigo Oliveira <rodrigo.oliveira@byne.com.br>
|
||||
Gyuri Horak <dyuri@horak.hu>
|
||||
Daniel Smith <malorian@me.com>
|
||||
Nils ANDRÉ-CHANG <nils@nilsand.re>
|
||||
chengxuncc <chengxuncc@gmail.com>
|
||||
nedsociety <nedsociety@gmail.com>
|
||||
fanosta <github@nageler.org>
|
||||
David Kalliecharan <david@david.science>
|
||||
Mike Crowe <drmikecrowe@gmail.com> drmikecrowe <drmikecrowe@gmail.com>
|
||||
Sylvain Corlay <sylvain.corlay@gmail.com>
|
||||
Chris Lasher <chris.lasher@gmail.com>
|
||||
Marcio Mazza <marciomazza@gmail.com>
|
||||
Jerzy Drozdz <jerzy.drozdz@gmail.com>
|
||||
goodboy <tgoodlet@users.noreply.github.com>
|
||||
Atsushi Morimoto <atsushi.morimoto@dena.com>
|
||||
|
|
13
AUTHORS.rst
13
AUTHORS.rst
|
@ -13,8 +13,8 @@ Authors are sorted by number of commits.
|
|||
* Jean-Benoist Leger
|
||||
* christopher
|
||||
* Klaus Alexander Seistrup
|
||||
* Leonardo Santagada
|
||||
* David Strobach
|
||||
* Leonardo Santagada
|
||||
* Burak Yiğit Kaya
|
||||
* Aaron Griffin
|
||||
* Rob Brewer
|
||||
|
@ -26,6 +26,7 @@ Authors are sorted by number of commits.
|
|||
* Gordon Ball
|
||||
* Travis Shirk
|
||||
* Joel Gerber
|
||||
* anki-code
|
||||
* vaaaaanquish
|
||||
* Bernardas Ališauskas
|
||||
* Derek Thomas
|
||||
|
@ -37,7 +38,6 @@ Authors are sorted by number of commits.
|
|||
* Frank Sachsenheim
|
||||
* Kurtis Rader
|
||||
* cryzed
|
||||
* anki-code
|
||||
* Brian Visel
|
||||
* Andrew Hundt
|
||||
* Jonathan Slenders
|
||||
|
@ -66,6 +66,7 @@ Authors are sorted by number of commits.
|
|||
* Nathan Goldbaum
|
||||
* mel
|
||||
* Jared Crawford
|
||||
* Mike Crowe
|
||||
* JuanPablo
|
||||
* Ollie Terrance
|
||||
* Marcel Bollmann
|
||||
|
@ -123,6 +124,7 @@ Authors are sorted by number of commits.
|
|||
* Sébastien Pierre
|
||||
* shadow-light
|
||||
* Jan Chren
|
||||
* Samuel Lotz
|
||||
* Mark Wiebe
|
||||
* Nathan Hoad
|
||||
* Eric Dill
|
||||
|
@ -145,11 +147,15 @@ Authors are sorted by number of commits.
|
|||
* Steven Kryskalla
|
||||
* cclauss
|
||||
* Eddie Peters
|
||||
* Gyuri Horak
|
||||
* Ke Zhang
|
||||
* László Vaskó
|
||||
* Allan Crooks
|
||||
* micimize
|
||||
* Edmund Miller
|
||||
* Noortheen Raja
|
||||
* Gabriel Vogel
|
||||
* anki
|
||||
* Dan Allan
|
||||
* Ned Letcher
|
||||
* Zach Crownover
|
||||
|
@ -206,16 +212,15 @@ Authors are sorted by number of commits.
|
|||
* Ronny Pfannschmidt
|
||||
* Troy de Freitas
|
||||
* Rodrigo Oliveira
|
||||
* Gyuri Horak
|
||||
* Daniel Smith
|
||||
* Nils ANDRÉ-CHANG
|
||||
* chengxuncc
|
||||
* nedsociety
|
||||
* fanosta
|
||||
* David Kalliecharan
|
||||
* Mike Crowe
|
||||
* Sylvain Corlay
|
||||
* Chris Lasher
|
||||
* Marcio Mazza
|
||||
* Jerzy Drozdz
|
||||
* goodboy
|
||||
* Atsushi Morimoto
|
||||
|
|
|
@ -4,6 +4,51 @@ Xonsh Change Log
|
|||
|
||||
.. current developments
|
||||
|
||||
v0.9.15
|
||||
====================
|
||||
|
||||
**Added:**
|
||||
|
||||
* Adds documentation for how to setup an emacs editing mode for xonsh.
|
||||
* New ``$XONSH_TRACE_SUBPROC`` environment variable.
|
||||
* Added ``-l``, ``-c`` and ``-a`` options to ``xexec``, works now like ``exec``
|
||||
in bash/zsh
|
||||
* **$HISTCONTROL** - *errordups* support for history-sqlite backend
|
||||
|
||||
**Changed:**
|
||||
|
||||
* ``-l`` switch works like bash, loads environment in non-interactive shell
|
||||
* The xonsh pytest plugin no longer messes up the test order for pytest. Xsh test
|
||||
are still executed first to avoid a bug were other tests would prevent ``test_*.xsh``
|
||||
files to run correctly.
|
||||
* New repo name for xxh
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* Correctly follow symlinks when using dot-dot paths with cd -P.
|
||||
* ``execx`` does not require the input string to be newline-terminated.
|
||||
* ``evalx`` accepts newline-terminated input string.
|
||||
* Fixed issue where negative exit codes (such as those produced
|
||||
by core dumps) where treated as logical successes when chaining
|
||||
processes with other boolean expressions.
|
||||
* Fixed XONSH_TRACE_SUBPROC for pipeline command.
|
||||
* updated CONTRIBUTING.rst about running pylint for changed files
|
||||
|
||||
**Authors:**
|
||||
|
||||
* Anthony Scopatz
|
||||
* Morten Enemark Lund
|
||||
* David Strobach
|
||||
* anki-code
|
||||
* Samuel Lotz
|
||||
* Gyuri Horak
|
||||
* Noortheen Raja
|
||||
* Gabriel Vogel
|
||||
* anki
|
||||
* Jerzy Drozdz
|
||||
|
||||
|
||||
|
||||
v0.9.14
|
||||
====================
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ as mispelled variable names, using pylint. If you're using Anaconda you'll
|
|||
need to run "conda install pylint" once. You can easily run pylint on
|
||||
the edited files in your uncommited git change::
|
||||
|
||||
$ pylint $(git status -s | awk '/\.py$$/ { print $$2 }' | sort)
|
||||
$ git status -s | awk '/\.py$$/ { print $2 }' | xargs pylint
|
||||
|
||||
If you want to lint the entire code base run::
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
* Added ``abbrevs`` xontrib.
|
||||
|
||||
**Changed:**
|
||||
|
||||
* New repo name for xxh
|
||||
* <news item>
|
||||
|
||||
**Deprecated:**
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
* Added `xontrib-pyenv <https://github.com/dyuri/xontrib-pyenv>`_ to list of registered xontribs.
|
||||
|
||||
**Changed:**
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
**Fixed:**
|
||||
|
||||
* Correctly follow symlinks when using dot-dot paths with cd -P.
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
**Added:**
|
||||
|
||||
* Adds documentation for how to setup an emacs editing mode for xonsh.
|
||||
|
||||
**Changed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -1,23 +0,0 @@
|
|||
**Added:**
|
||||
|
||||
* New ``$XONSH_TRACE_SUBPROC`` environment variable.
|
||||
|
||||
**Changed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -1,25 +0,0 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Changed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* Fixed issue where negative exit codes (such as those produced
|
||||
by core dumps) where treated as logical successes when chaining
|
||||
processes with other boolean expressions.
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -1,24 +0,0 @@
|
|||
**Added:**
|
||||
|
||||
* Added ``-l``, ``-c`` and ``-a`` options to ``xexec``, works now like ``exec``
|
||||
in bash/zsh
|
||||
|
||||
**Changed:**
|
||||
|
||||
* ``-l`` switch works like bash, loads environment in non-interactive shell
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -1,25 +0,0 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Changed:**
|
||||
|
||||
* The xonsh pytest plugin no longer messes up the test order for pytest. Xsh test
|
||||
are still executed first to avoid a bug were other tests would prevent ``test_*.xsh``
|
||||
files to run correctly.
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -1,23 +0,0 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Changed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* Fixed XONSH_TRACE_SUBPROC for pipeline command.
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -101,6 +101,14 @@ def test_histcontrol_ignoreerr_ignoredups():
|
|||
assert "ignoredups" in env["HISTCONTROL"]
|
||||
|
||||
|
||||
def test_histcontrol_ignoreerr_ignoredups_erase_dups():
|
||||
env = Env(HISTCONTROL="ignoreerr,ignoredups,ignoreerr,erasedups")
|
||||
assert len(env["HISTCONTROL"]) == 3
|
||||
assert "ignoreerr" in env["HISTCONTROL"]
|
||||
assert "ignoredups" in env["HISTCONTROL"]
|
||||
assert "erasedups" in env["HISTCONTROL"]
|
||||
|
||||
|
||||
def test_swap():
|
||||
env = Env(VAR="wakka")
|
||||
assert env["VAR"] == "wakka"
|
||||
|
|
|
@ -2,7 +2,13 @@
|
|||
"""Tests the xonsh lexer."""
|
||||
import os
|
||||
|
||||
from tools import check_eval, check_parse, skip_if_on_unix, skip_if_on_windows
|
||||
from tools import (
|
||||
check_eval,
|
||||
check_exec,
|
||||
check_parse,
|
||||
skip_if_on_unix,
|
||||
skip_if_on_windows,
|
||||
)
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -138,3 +144,12 @@ def test_echo_line_cont():
|
|||
)
|
||||
def test_two_echo_line_cont(code):
|
||||
assert check_parse(code)
|
||||
|
||||
|
||||
def test_eval_eol():
|
||||
assert check_eval("0") and check_eval("0\n")
|
||||
|
||||
|
||||
def test_exec_eol():
|
||||
locs = dict()
|
||||
assert check_exec("a=0", locs=locs) and check_exec("a=0\n", locs=locs)
|
||||
|
|
|
@ -169,6 +169,27 @@ def test_histcontrol(hist, xonsh_builtins):
|
|||
assert -1 == hist.rtns[-1]
|
||||
|
||||
|
||||
def test_histcontrol_erase_dup(hist, xonsh_builtins):
|
||||
"""Test HISTCONTROL=erasedups"""
|
||||
|
||||
xonsh_builtins.__xonsh__.env["HISTCONTROL"] = "erasedups"
|
||||
assert len(hist) == 0
|
||||
|
||||
hist.append({"inp": "ls foo", "rtn": 2})
|
||||
hist.append({"inp": "ls foobazz", "rtn": 0})
|
||||
hist.append({"inp": "ls foo", "rtn": 0})
|
||||
hist.append({"inp": "ls foobazz", "rtn": 0})
|
||||
hist.append({"inp": "ls foo", "rtn": 0})
|
||||
assert len(hist) == 2
|
||||
assert len(hist.inps) == 5
|
||||
|
||||
items = list(hist.items())
|
||||
assert "ls foo" == items[-1]["inp"]
|
||||
assert "ls foobazz" == items[-2]["inp"]
|
||||
assert items[-2]["frequency"] == 2
|
||||
assert items[-1]["frequency"] == 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"index, exp",
|
||||
[
|
||||
|
|
|
@ -174,8 +174,6 @@ class DummyEnv(MutableMapping):
|
|||
|
||||
|
||||
def check_exec(input, **kwargs):
|
||||
if not input.endswith("\n"):
|
||||
input += "\n"
|
||||
builtins.__xonsh__.execer.exec(input, **kwargs)
|
||||
return True
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
__version__ = "0.9.14"
|
||||
__version__ = "0.9.15"
|
||||
|
||||
|
||||
# amalgamate exclude jupyter_kernel parser_table parser_test_table pyghooks
|
||||
|
|
|
@ -1004,8 +1004,10 @@ def DEFAULT_DOCS():
|
|||
"that determine what commands are saved to the history list. By "
|
||||
"default all commands are saved. The option ``ignoredups`` will not "
|
||||
"save the command if it matches the previous command. The option "
|
||||
"'ignoreerr' will cause any commands that fail (i.e. return non-zero "
|
||||
"exit status) to not be added to the history list.",
|
||||
"``ignoreerr`` will cause any commands that fail (i.e. return non-zero "
|
||||
"exit status) to not be added to the history list. The option "
|
||||
"``erasedups`` will remove all previous commands that matches and updates the frequency. "
|
||||
"Note: ``erasedups`` is supported only in sqlite backend).",
|
||||
store_as_str=True,
|
||||
),
|
||||
"IGNOREEOF": VarDocs("Prevents Ctrl-D from exiting the shell."),
|
||||
|
|
|
@ -145,6 +145,7 @@ class Execer(object):
|
|||
if isinstance(input, types.CodeType):
|
||||
code = input
|
||||
else:
|
||||
input = input.rstrip("\n")
|
||||
if filename is None:
|
||||
filename = self.filename
|
||||
code = self.compile(
|
||||
|
@ -174,6 +175,8 @@ class Execer(object):
|
|||
if isinstance(input, types.CodeType):
|
||||
code = input
|
||||
else:
|
||||
if not input.endswith("\n"):
|
||||
input += "\n"
|
||||
if filename is None:
|
||||
filename = self.filename
|
||||
code = self.compile(
|
||||
|
|
|
@ -12,6 +12,10 @@ import time
|
|||
from xonsh.history.base import History
|
||||
import xonsh.tools as xt
|
||||
|
||||
XH_SQLITE_CACHE = threading.local()
|
||||
XH_SQLITE_TABLE_NAME = "xonsh_history"
|
||||
XH_SQLITE_CREATED_SQL_TBL = "CREATED_SQL_TABLE"
|
||||
|
||||
|
||||
def _xh_sqlite_get_file_name():
|
||||
envs = builtins.__xonsh__.env
|
||||
|
@ -33,35 +37,84 @@ def _xh_sqlite_create_history_table(cursor):
|
|||
|
||||
Columns:
|
||||
info - JSON formatted, reserved for future extension.
|
||||
frequency - in case of HISTCONTROL=erasedups,
|
||||
it tracks the frequency of the inputs. helps in sorting autocompletion
|
||||
"""
|
||||
if not getattr(XH_SQLITE_CACHE, XH_SQLITE_CREATED_SQL_TBL, False):
|
||||
cursor.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS {}
|
||||
(inp TEXT,
|
||||
rtn INTEGER,
|
||||
tsb REAL,
|
||||
tse REAL,
|
||||
sessionid TEXT,
|
||||
out TEXT,
|
||||
info TEXT,
|
||||
frequency INTEGER default 1
|
||||
)
|
||||
""".format(
|
||||
XH_SQLITE_TABLE_NAME
|
||||
)
|
||||
)
|
||||
# add frequency column if not exists for backward compatibility
|
||||
try:
|
||||
cursor.execute(
|
||||
"ALTER TABLE "
|
||||
+ XH_SQLITE_TABLE_NAME
|
||||
+ " ADD COLUMN frequency INTEGER default 1"
|
||||
)
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
|
||||
# mark that this function ran for this session
|
||||
setattr(XH_SQLITE_CACHE, XH_SQLITE_CREATED_SQL_TBL, True)
|
||||
|
||||
|
||||
def _xh_sqlite_get_frequency(cursor, input):
|
||||
# type: (sqlite3.Cursor, str) -> int
|
||||
sql = "SELECT sum(frequency) FROM {} WHERE inp=?".format(XH_SQLITE_TABLE_NAME)
|
||||
cursor.execute(sql, (input,))
|
||||
return cursor.fetchone()[0] or 0
|
||||
|
||||
|
||||
def _xh_sqlite_erase_dups(cursor, input):
|
||||
freq = _xh_sqlite_get_frequency(cursor, input)
|
||||
sql = "DELETE FROM {} WHERE inp=?".format(XH_SQLITE_TABLE_NAME)
|
||||
cursor.execute(sql, (input,))
|
||||
return freq
|
||||
|
||||
|
||||
def _sql_insert(cursor, values):
|
||||
# type: (sqlite3.Cursor, dict) -> None
|
||||
"""handy function to run insert query"""
|
||||
sql = "INSERT INTO {} ({}) VALUES ({});"
|
||||
fields = ", ".join(values)
|
||||
marks = ", ".join(["?"] * len(values))
|
||||
cursor.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS xonsh_history
|
||||
(inp TEXT,
|
||||
rtn INTEGER,
|
||||
tsb REAL,
|
||||
tse REAL,
|
||||
sessionid TEXT,
|
||||
out TEXT,
|
||||
info TEXT
|
||||
)
|
||||
"""
|
||||
sql.format(XH_SQLITE_TABLE_NAME, fields, marks), tuple(values.values())
|
||||
)
|
||||
|
||||
|
||||
def _xh_sqlite_insert_command(cursor, cmd, sessionid, store_stdout):
|
||||
sql = "INSERT INTO xonsh_history (inp, rtn, tsb, tse, sessionid"
|
||||
def _xh_sqlite_insert_command(cursor, cmd, sessionid, store_stdout, remove_duplicates):
|
||||
tss = cmd.get("ts", [None, None])
|
||||
params = [cmd["inp"].rstrip(), cmd["rtn"], tss[0], tss[1], sessionid]
|
||||
values = collections.OrderedDict(
|
||||
[
|
||||
("inp", cmd["inp"].rstrip()),
|
||||
("rtn", cmd["rtn"]),
|
||||
("tsb", tss[0]),
|
||||
("tse", tss[1]),
|
||||
("sessionid", sessionid),
|
||||
]
|
||||
)
|
||||
if store_stdout and "out" in cmd:
|
||||
sql += ", out"
|
||||
params.append(cmd["out"])
|
||||
values["out"] = cmd["out"]
|
||||
if "info" in cmd:
|
||||
sql += ", info"
|
||||
info = json.dumps(cmd["info"])
|
||||
params.append(info)
|
||||
sql += ") VALUES (" + ("?, " * len(params)).rstrip(", ") + ")"
|
||||
cursor.execute(sql, tuple(params))
|
||||
values["info"] = info
|
||||
if remove_duplicates:
|
||||
values["frequency"] = _xh_sqlite_erase_dups(cursor, values["inp"]) + 1
|
||||
_sql_insert(cursor, values)
|
||||
|
||||
|
||||
def _xh_sqlite_get_count(cursor, sessionid=None):
|
||||
|
@ -75,7 +128,7 @@ def _xh_sqlite_get_count(cursor, sessionid=None):
|
|||
|
||||
|
||||
def _xh_sqlite_get_records(cursor, sessionid=None, limit=None, newest_first=False):
|
||||
sql = "SELECT inp, tsb, rtn FROM xonsh_history "
|
||||
sql = "SELECT inp, tsb, rtn, frequency FROM xonsh_history "
|
||||
params = []
|
||||
if sessionid is not None:
|
||||
sql += "WHERE sessionid = ? "
|
||||
|
@ -103,11 +156,13 @@ def _xh_sqlite_delete_records(cursor, size_to_keep):
|
|||
return result.rowcount
|
||||
|
||||
|
||||
def xh_sqlite_append_history(cmd, sessionid, store_stdout, filename=None):
|
||||
def xh_sqlite_append_history(
|
||||
cmd, sessionid, store_stdout, filename=None, remove_duplicates=False
|
||||
):
|
||||
with _xh_sqlite_get_conn(filename=filename) as conn:
|
||||
c = conn.cursor()
|
||||
_xh_sqlite_create_history_table(c)
|
||||
_xh_sqlite_insert_command(c, cmd, sessionid, store_stdout)
|
||||
_xh_sqlite_insert_command(c, cmd, sessionid, store_stdout, remove_duplicates)
|
||||
conn.commit()
|
||||
|
||||
|
||||
|
@ -181,9 +236,11 @@ class SqliteHistory(History):
|
|||
self.outs = []
|
||||
self.tss = []
|
||||
|
||||
# during init rerun create command
|
||||
setattr(XH_SQLITE_CACHE, XH_SQLITE_CREATED_SQL_TBL, False)
|
||||
|
||||
def append(self, cmd):
|
||||
envs = builtins.__xonsh__.env
|
||||
opts = envs.get("HISTCONTROL")
|
||||
inp = cmd["inp"].rstrip()
|
||||
self.inps.append(inp)
|
||||
store_stdout = envs.get("XONSH_STORE_STDOUT", False)
|
||||
|
@ -203,22 +260,23 @@ class SqliteHistory(History):
|
|||
return
|
||||
self._last_hist_inp = inp
|
||||
xh_sqlite_append_history(
|
||||
cmd, str(self.sessionid), store_stdout, filename=self.filename
|
||||
cmd,
|
||||
str(self.sessionid),
|
||||
store_stdout,
|
||||
filename=self.filename,
|
||||
remove_duplicates=("erasedups" in opts),
|
||||
)
|
||||
|
||||
def all_items(self, newest_first=False):
|
||||
def all_items(self, newest_first=False, session_id=None):
|
||||
"""Display all history items."""
|
||||
for item in xh_sqlite_items(filename=self.filename, newest_first=newest_first):
|
||||
yield {"inp": item[0], "ts": item[1], "rtn": item[2]}
|
||||
for inp, ts, rtn, freq in xh_sqlite_items(
|
||||
filename=self.filename, newest_first=newest_first, sessionid=session_id
|
||||
):
|
||||
yield {"inp": inp, "ts": ts, "rtn": rtn, "frequency": freq}
|
||||
|
||||
def items(self, newest_first=False):
|
||||
"""Display history items of current session."""
|
||||
for item in xh_sqlite_items(
|
||||
sessionid=str(self.sessionid),
|
||||
filename=self.filename,
|
||||
newest_first=newest_first,
|
||||
):
|
||||
yield {"inp": item[0], "ts": item[1], "rtn": item[2]}
|
||||
yield from self.all_items(newest_first, session_id=str(self.sessionid))
|
||||
|
||||
def info(self):
|
||||
data = collections.OrderedDict()
|
||||
|
|
|
@ -1,4 +1,17 @@
|
|||
{"xontribs": [
|
||||
{"name": "abbrevs",
|
||||
"package": "xonsh",
|
||||
"url": "http://xon.sh",
|
||||
"description": [
|
||||
"Adds ``abbrevs`` dictionary to hold user-defined command abbreviations. ",
|
||||
"The dictionary is searched as you type and the matching words are replaced ",
|
||||
"at the command line by the corresponding dictionary contents once you hit ",
|
||||
"'Space' or 'Return' key. For instance a frequently used command such as ",
|
||||
"``git status`` can be abbreviated to ``gst`` as follows::\n\n",
|
||||
" $ xontrib load abbrevs\n",
|
||||
" $ abbrevs['gst'] = 'git status'\n",
|
||||
" $ gst # Once you hit <space> or <return>, 'gst' gets expanded to 'git status'.\n\n"]
|
||||
},
|
||||
{"name": "apt_tabcomplete",
|
||||
"package": "xonsh-apt-tabcomplete",
|
||||
"url": "https://github.com/DangerOnTheRanger/xonsh-apt-tabcomplete",
|
||||
|
@ -146,11 +159,16 @@
|
|||
"url": "https://github.com/t184256/xontrib-prompt-vi-mode",
|
||||
"description": ["vi-mode status formatter for xonsh prompt"]
|
||||
},
|
||||
{"name": "pyenv",
|
||||
"package": "xontrib-pyenv",
|
||||
"url": "https://github.com/dyuri/xontrib-pyenv",
|
||||
"description": ["pyenv integration for xonsh."]
|
||||
},
|
||||
{"name": "readable-traceback",
|
||||
"package": "xontrib-readable-traceback",
|
||||
"url": "https://github.com/6syun9/xontrib-readable-traceback",
|
||||
"description": ["Make traceback easier to see for xonsh."]
|
||||
},
|
||||
},
|
||||
{"name": "schedule",
|
||||
"package": "xontrib-schedule",
|
||||
"url": "https://github.com/astronouth7303/xontrib-schedule",
|
||||
|
@ -299,6 +317,13 @@
|
|||
"pip": "xpip install xontrib-kitty"
|
||||
}
|
||||
},
|
||||
"xontrib-powerline": {
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/santagada/xontrib-powerline",
|
||||
"install": {
|
||||
"pip": "xpip install xontrib-powerline"
|
||||
}
|
||||
},
|
||||
"xontrib-prompt-ret-code": {
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/Siecje/xontrib-prompt-ret-code",
|
||||
|
@ -313,11 +338,11 @@
|
|||
"pip": "xpip install xontrib-prompt-vi-mode"
|
||||
}
|
||||
},
|
||||
"xontrib-powerline": {
|
||||
"xontrib-pyenv": {
|
||||
"license": "MIT",
|
||||
"url": "https://github.com/santagada/xontrib-powerline",
|
||||
"url": "https://github.com/dyuri/xontrib-pyenv",
|
||||
"install": {
|
||||
"pip": "xpip install xontrib-powerline"
|
||||
"pip": "xpip install xontrib-pyenv"
|
||||
}
|
||||
},
|
||||
"xontrib-readable-traceback": {
|
||||
|
|
65
xontrib/abbrevs.py
Normal file
65
xontrib/abbrevs.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
"""
|
||||
Command abbreviations.
|
||||
|
||||
This expands input words from `abbrevs` disctionary as you type.
|
||||
"""
|
||||
|
||||
import builtins
|
||||
from prompt_toolkit.filters import IsMultiline
|
||||
from prompt_toolkit.keys import Keys
|
||||
from xonsh.built_ins import DynamicAccessProxy
|
||||
from xonsh.platform import ptk_shell_type
|
||||
from xonsh.tools import check_for_partial_string
|
||||
|
||||
__all__ = ()
|
||||
|
||||
builtins.__xonsh__.abbrevs = dict()
|
||||
proxy = DynamicAccessProxy("abbrevs", "__xonsh__.abbrevs")
|
||||
setattr(builtins, "abbrevs", proxy)
|
||||
|
||||
|
||||
def expand_abbrev(buffer):
|
||||
abbrevs = getattr(builtins, "abbrevs", None)
|
||||
if abbrevs is None:
|
||||
return
|
||||
document = buffer.document
|
||||
word = document.get_word_before_cursor(WORD=True)
|
||||
if word in abbrevs.keys():
|
||||
partial = document.text[: document.cursor_position]
|
||||
startix, endix, quote = check_for_partial_string(partial)
|
||||
if startix is not None and endix is None:
|
||||
return
|
||||
buffer.delete_before_cursor(count=len(word))
|
||||
buffer.insert_text(abbrevs[word])
|
||||
|
||||
|
||||
@events.on_ptk_create
|
||||
def custom_keybindings(bindings, **kw):
|
||||
|
||||
if ptk_shell_type() == "prompt_toolkit2":
|
||||
from xonsh.ptk2.key_bindings import carriage_return
|
||||
from prompt_toolkit.filters import EmacsInsertMode, ViInsertMode
|
||||
|
||||
handler = bindings.add
|
||||
insert_mode = ViInsertMode() | EmacsInsertMode()
|
||||
else:
|
||||
from xonsh.ptk.key_bindings import carriage_return
|
||||
from prompt_toolkit.filters import to_filter
|
||||
|
||||
handler = bindings.registry.add_binding
|
||||
insert_mode = to_filter(True)
|
||||
|
||||
@handler(" ", filter=IsMultiline() & insert_mode)
|
||||
def handle_space(event):
|
||||
buffer = event.app.current_buffer
|
||||
expand_abbrev(buffer)
|
||||
buffer.insert_text(" ")
|
||||
|
||||
@handler(Keys.ControlJ, filter=IsMultiline() & insert_mode)
|
||||
@handler(Keys.ControlM, filter=IsMultiline() & insert_mode)
|
||||
def multiline_carriage_return(event):
|
||||
buffer = event.app.current_buffer
|
||||
current_char = buffer.document.current_char
|
||||
if not current_char or current_char.isspace():
|
||||
expand_abbrev(buffer)
|
||||
carriage_return(buffer, event.cli)
|
Loading…
Add table
Reference in a new issue