This commit is contained in:
Christian Nieves
2022-08-09 18:38:53 +00:00
parent 30874bd72d
commit 96b09edbe4
9 changed files with 263 additions and 0 deletions

2
hgshort/hgshort/OWNERS Normal file
View File

@ -0,0 +1,2 @@
parren
yurilev

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

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

View 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

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