hgshort
This commit is contained in:
2
hgshort/hgshort/OWNERS
Normal file
2
hgshort/hgshort/OWNERS
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
parren
|
||||||
|
yurilev
|
7
hgshort/hgshort/README.md
Normal file
7
hgshort/hgshort/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# hgshort - Single Letter Shorthands for Fig
|
||||||
|
|
||||||
|
hgshort makes it really easy to work with files and revisions in Fig. Use
|
||||||
|
**single letter** shorthand names, instead of long paths and hash codes.
|
||||||
|
|
||||||
|
Documentation can be found
|
||||||
|
[here](http://g3doc/experimental/fig_contrib/g3doc/hgshort).
|
21
hgshort/hgshort/aliases.sh
Normal file
21
hgshort/hgshort/aliases.sh
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Creates the recommended alias definitions for hgshort when sourced.
|
||||||
|
|
||||||
|
HGSHORT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}}")" && pwd)"
|
||||||
|
|
||||||
|
alias hg="source $HGSHORT_DIR/hgshort.sh"
|
||||||
|
|
||||||
|
# There are two ways to customize:
|
||||||
|
# - define HGSHORT_CMDS_ADDITIONAL in your shell configuration to augment the
|
||||||
|
# following list.
|
||||||
|
# - define HGSHORT_CMDS directly in your shell configuration to override the
|
||||||
|
# following list.
|
||||||
|
if [[ -z "$HGSHORT_CMDS" ]]; then
|
||||||
|
HGSHORT_CMDS="$HGSHORT_CMDS_ADDITIONAL ls cat head tail mv cp rm chmod g4 diff merge patch meld vim emacs edit trim less more"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Doing the variable expansion with an 'echo' makes this compatible with zsh.
|
||||||
|
for c in $(echo "$HGSHORT_CMDS"); do
|
||||||
|
alias $c="source $HGSHORT_DIR/tobashargs.sh $c"
|
||||||
|
done
|
12
hgshort/hgshort/hgd.sh
Executable file
12
hgshort/hgshort/hgd.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
HGSHORT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}}")" && pwd)"
|
||||||
|
|
||||||
|
source $HGSHORT_DIR/aliases.sh
|
||||||
|
cd $(hg hgd "$@")
|
||||||
|
|
||||||
|
CITC="${PWD#/google/src/cloud/$USER/}"
|
||||||
|
CITC="${CITC%/google3}"
|
||||||
|
echo "CitC $CITC"
|
||||||
|
|
||||||
|
hg l --color=always
|
73
hgshort/hgshort/hgshort.hgrc
Normal file
73
hgshort/hgshort/hgshort.hgrc
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# .hgrc for use with hgshort.
|
||||||
|
#
|
||||||
|
# Adds generated single letter revision and file shorthand names to the outputs
|
||||||
|
# of 'hg l/xl/ll' and 'hg status'.
|
||||||
|
#
|
||||||
|
# * For hg l/xl/ll, modifies the defaults set by:
|
||||||
|
# http://google3/devtools/piper/hgfission/client/config/google-ui-tweaks.rc
|
||||||
|
#
|
||||||
|
# * For hg status, overrides the default template (no extensible template
|
||||||
|
# available), but with one that looks the same.
|
||||||
|
#
|
||||||
|
# To use, add the following line to your ~/.hgrc:
|
||||||
|
# %include /google/src/head/depot/google3/experimental/fig_contrib/hgshort/hgshort.hgrc
|
||||||
|
#
|
||||||
|
# To make hg and other commands actually recognize the outputted shorthand
|
||||||
|
# names, follow go/hgshort#initial-setup.
|
||||||
|
#
|
||||||
|
# If you have already customized the outputs of 'hg l/xl/ll' or 'hg status',
|
||||||
|
# including this file would override them. Instead:
|
||||||
|
#
|
||||||
|
# * If you only aliased or added default arguments for 'hg status', add the
|
||||||
|
# following argument:
|
||||||
|
# --template=hgshort_status
|
||||||
|
#
|
||||||
|
# * If you customized the outputs themselves, copy the "extensions" and
|
||||||
|
# optionally the "color" sections and use:
|
||||||
|
#
|
||||||
|
# + hgshort_revision_shorthand — in your log templates.
|
||||||
|
# + hgshort_file_shorthand — in your status templates.
|
||||||
|
|
||||||
|
[extensions]
|
||||||
|
hgshort = /google/src/head/depot/google3/experimental/fig_contrib/hgshort/hgshort.py
|
||||||
|
|
||||||
|
[color]
|
||||||
|
# The color used for hgshort's single letter aliases.
|
||||||
|
hgshort.alias = red bold
|
||||||
|
|
||||||
|
[color256]
|
||||||
|
# The color used for hgshort's single letter aliases.
|
||||||
|
hgshort.alias = orange bold
|
||||||
|
|
||||||
|
##### hg l/xl/ll configuration #####
|
||||||
|
|
||||||
|
[templatealias]
|
||||||
|
# Get an alias for the current revision (node) with an uppercase letter.
|
||||||
|
hgshort_revision_shorthand='{hgshort(node,"A")}'
|
||||||
|
# Add the revision hgshort shorthand name to the output of 'hg l/xl/ll'.
|
||||||
|
google_compact_line_1_part_1 = '{hgshort_revision_shorthand}{google_compact_uniq_id}'
|
||||||
|
|
||||||
|
##### hg status configuration #####
|
||||||
|
|
||||||
|
[templatealias]
|
||||||
|
# Get an alias for the current file with a lowercase letter.
|
||||||
|
hgshort_file_shorthand='{hgshort(relpath(path),"a")}'
|
||||||
|
# Get the right built-in label (style) for the file's status.
|
||||||
|
# See http://screen/8A5ynkOdEED.png for an example output,
|
||||||
|
# and 'hg help status' for details.
|
||||||
|
hgshort_status_label(status) = '{ifeq(status, "?", "status.unknown", ifeq(status, "!", "status.deleted", get(dict(A="status.added", M="status.modified", R="status.removed", I="status.ignored", C="status.clean"), status)))}'
|
||||||
|
hgshort_status_line1 = '{hgshort_file_shorthand}{label(hgshort_status_label(status), '{status} {relpath(path)}')}'
|
||||||
|
hgshort_status_line2 = '{if(source, " {label("status.copied", " {relpath(source)}")}")}'
|
||||||
|
|
||||||
|
[templates]
|
||||||
|
# Add the hgshort file shorthand name to the output of 'hg status'.
|
||||||
|
# In conflict resolution mode, we get empty entries. Filter them out.
|
||||||
|
hgshort_status = '{if(path,"{separate("\n", hgshort_status_line1, hgshort_status_line2)}\n","")}'
|
||||||
|
|
||||||
|
[defaults]
|
||||||
|
# Override the default 'hg status' command, but keep -n working.
|
||||||
|
status = --template=hgshort_status
|
||||||
|
|
||||||
|
[alias]
|
||||||
|
# Override the default 'hg pstatus' template.
|
||||||
|
pstatus = pstatus --template=hgshort_status
|
82
hgshort/hgshort/hgshort.py
Normal file
82
hgshort/hgshort/hgshort.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
'''"shorthand" template filter to emit bash shorthand accessors.'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from mercurial import error
|
||||||
|
from mercurial import i18n
|
||||||
|
from mercurial import registrar
|
||||||
|
from mercurial import templateutil
|
||||||
|
|
||||||
|
# dict of template built-in functions
|
||||||
|
funcs = {}
|
||||||
|
templatefunc = registrar.templatefunc(funcs)
|
||||||
|
templatefilter = registrar.templatefilter()
|
||||||
|
|
||||||
|
evalboolean = templateutil.evalboolean
|
||||||
|
evalstring = templateutil.evalstring
|
||||||
|
|
||||||
|
bashvarsfile = None
|
||||||
|
if sys.stdout.isatty():
|
||||||
|
if 'HGSHORT_BASH_VARS' in os.environ:
|
||||||
|
bashvarsfile = os.environ['HGSHORT_BASH_VARS']
|
||||||
|
|
||||||
|
nextaliasidbytype = {
|
||||||
|
b'a': ord(b'a'),
|
||||||
|
b'A': ord(b'A')}
|
||||||
|
|
||||||
|
|
||||||
|
def writealias(name, value):
|
||||||
|
if not bashvarsfile:
|
||||||
|
return
|
||||||
|
with open(bashvarsfile, 'a') as f:
|
||||||
|
f.write("export %s='%s'\n" % (name.decode('utf-8'), value.decode('utf-8')))
|
||||||
|
|
||||||
|
|
||||||
|
def nextaliaschar(aliastype):
|
||||||
|
if not bashvarsfile:
|
||||||
|
return None
|
||||||
|
aliasid = nextaliasidbytype[aliastype]
|
||||||
|
if aliasid < ord(aliastype) + 26:
|
||||||
|
nextaliasidbytype[aliastype] += 1
|
||||||
|
return chr(aliasid).encode('utf-8')
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def maybealias(value, aliastype):
|
||||||
|
"""Export as next bash alias and return id, or None."""
|
||||||
|
aliaschar = nextaliaschar(aliastype)
|
||||||
|
if not aliaschar: return None
|
||||||
|
writealias(b'hgshort%s' % aliaschar, value)
|
||||||
|
return aliaschar
|
||||||
|
|
||||||
|
|
||||||
|
@templatefilter(b'shorthand', intype=bytes)
|
||||||
|
def shorthand(text):
|
||||||
|
"""Export as next bash alias."""
|
||||||
|
if not bashvarsfile:
|
||||||
|
return b''
|
||||||
|
aliaschar = maybealias(text, b'a')
|
||||||
|
if not aliaschar:
|
||||||
|
return b' '
|
||||||
|
return b'%s ' % aliaschar
|
||||||
|
|
||||||
|
|
||||||
|
@templatefunc(
|
||||||
|
b'hgshort(text, aliastype)',
|
||||||
|
argspec=b'text aliastype',
|
||||||
|
requires={b'ui'})
|
||||||
|
def hgshort(context, mapping, args):
|
||||||
|
"""Export as next bash alias and return id, or None."""
|
||||||
|
if not bashvarsfile:
|
||||||
|
return b''
|
||||||
|
if b'text' not in args or b'aliastype' not in args:
|
||||||
|
raise error.ParseError(i18n._(b'hgshort() expects one to three arguments'))
|
||||||
|
text = evalstring(context, mapping, args[b'text'])
|
||||||
|
aliastype = evalstring(context, mapping, args[b'aliastype'])
|
||||||
|
aliaschar = maybealias(text, aliastype)
|
||||||
|
if not aliaschar:
|
||||||
|
return b' '
|
||||||
|
aliastext = b'%s ' % aliaschar
|
||||||
|
ui = context.resource(mapping, b'ui')
|
||||||
|
return ui.label(aliastext, b'hgshort.alias')
|
20
hgshort/hgshort/hgshort.sh
Executable file
20
hgshort/hgshort/hgshort.sh
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
HGSHORT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}}")" && pwd)"
|
||||||
|
|
||||||
|
export HGSHORT_BASH_VARS="/tmp/hgshort-bash-vars-$$.sh"
|
||||||
|
export HGSHORT_BASH_ARGS="/tmp/hgshort-bash-args-$$.sh"
|
||||||
|
|
||||||
|
if [[ -f $HGSHORT_BASH_VARS ]]; then
|
||||||
|
\rm $HGSHORT_BASH_VARS # don't call rm to avoid alias loop
|
||||||
|
fi
|
||||||
|
|
||||||
|
HGSHORT_IS_HG=1 $HGSHORT_DIR/tobashargs.py "$@" > $HGSHORT_BASH_ARGS
|
||||||
|
xargs --null --arg-file=$HGSHORT_BASH_ARGS \
|
||||||
|
hg --config extensions.hgshort=$HGSHORT_DIR/hgshort.py
|
||||||
|
\rm $HGSHORT_BASH_ARGS # don't call rm to avoid alias loop
|
||||||
|
|
||||||
|
if [[ -f $HGSHORT_BASH_VARS ]]; then
|
||||||
|
source $HGSHORT_BASH_VARS
|
||||||
|
\rm $HGSHORT_BASH_VARS # don't call rm to avoid alias loop
|
||||||
|
fi
|
35
hgshort/hgshort/tobashargs.py
Executable file
35
hgshort/hgshort/tobashargs.py
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
"""Converts single letters like X to bash variable references like $hgshortX."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Shortands can be prefixed with an 'r', in which case several can be used in
|
||||||
|
# one argument. This is useful for revsets, for example: 'rA::rD'.
|
||||||
|
ALIAS_RE = re.compile(r'^([a-zA-Z])$|\br([A-Z])\b')
|
||||||
|
|
||||||
|
|
||||||
|
def subst(match):
|
||||||
|
char = match.group(1) or match.group(2)
|
||||||
|
|
||||||
|
var = 'hgshort%s' % char
|
||||||
|
if var in os.environ:
|
||||||
|
return os.getenv(var, '')
|
||||||
|
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
|
||||||
|
def substall(s):
|
||||||
|
return ALIAS_RE.sub(subst, s)
|
||||||
|
|
||||||
|
|
||||||
|
# Don't process first argument for `hg`, since it's often a command abbreviated
|
||||||
|
# to a single letter.
|
||||||
|
if 'HGSHORT_IS_HG' in os.environ:
|
||||||
|
args = sys.argv[1:2] + list(substall(a) for a in sys.argv[2:])
|
||||||
|
else:
|
||||||
|
args = list(substall(a) for a in sys.argv[1:])
|
||||||
|
|
||||||
|
# sys.stderr.write('%s\n' % repr(args)) # debug only
|
||||||
|
sys.stdout.write(chr(0).join(args))
|
11
hgshort/hgshort/tobashargs.sh
Executable file
11
hgshort/hgshort/tobashargs.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
HGSHORT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}}")" && pwd)"
|
||||||
|
|
||||||
|
export HGSHORT_BASH_CMD="$1"
|
||||||
|
export HGSHORT_BASH_ARGS="/tmp/HGSHORT-bash-args-$$.sh"
|
||||||
|
|
||||||
|
shift
|
||||||
|
$HGSHORT_DIR/tobashargs.py "$@" > $HGSHORT_BASH_ARGS
|
||||||
|
xargs --null --arg-file=$HGSHORT_BASH_ARGS $HGSHORT_BASH_CMD
|
||||||
|
\rm $HGSHORT_BASH_ARGS # don't call rm to avoid alias loop
|
Reference in New Issue
Block a user