Merge branch 'master' into is3474

This commit is contained in:
Bob Hyman 2020-03-29 16:14:54 -04:00
commit 65e639eb88
24 changed files with 339 additions and 207 deletions

View file

@ -1,4 +1,4 @@
version: 0.9.14.{build}
version: 0.9.15.{build}
os: Windows Server 2012 R2
environment:

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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
====================

View file

@ -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::

View file

@ -1,10 +1,10 @@
**Added:**
* <news item>
* Added ``abbrevs`` xontrib.
**Changed:**
* New repo name for xxh
* <news item>
**Deprecated:**

View file

@ -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:**

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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"

View file

@ -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)

View file

@ -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",
[

View file

@ -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

View file

@ -1,4 +1,4 @@
__version__ = "0.9.14"
__version__ = "0.9.15"
# amalgamate exclude jupyter_kernel parser_table parser_test_table pyghooks

View file

@ -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."),

View file

@ -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(

View file

@ -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()

View file

@ -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
View 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)