Patchwork contrib: check completionhints file for possible completions

login
register
mail settings
Submitter Gulshan Singh
Date Sept. 15, 2015, 8:30 p.m.
Message ID <4e3b6c50e59e493d6ef5.1442349008@dev3597.prn1.facebook.com>
Download mbox | patch
Permalink /patch/10514/
State Deferred
Delegated to: Matt Mackall
Headers show

Comments

Gulshan Singh - Sept. 15, 2015, 8:30 p.m.
# HG changeset patch
# User Gulshan Singh <gulshan@fb.com>
# Date 1441845115 25200
#      Wed Sep 09 17:31:55 2015 -0700
# Node ID 4e3b6c50e59e493d6ef557476f962770787ba3c3
# Parent  ab1c6e4efda47281b14a4f5a46cc0d4a114fff7d
contrib: check completionhints file for possible completions

Check a file called completionhints in the .hg directory for possible completions.
Each line of this file can be a possible completion. This is useful so we can store
things like recently viewed hashes in this file and use them for completion, and
at some point allow us to do bookmark autocompletion without executing hg.
Matt Mackall - Sept. 16, 2015, 7:52 p.m.
On Tue, 2015-09-15 at 13:30 -0700, Gulshan Singh wrote:
> # HG changeset patch
> # User Gulshan Singh <gulshan@fb.com>
> # Date 1441845115 25200
> #      Wed Sep 09 17:31:55 2015 -0700
> # Node ID 4e3b6c50e59e493d6ef557476f962770787ba3c3
> # Parent  ab1c6e4efda47281b14a4f5a46cc0d4a114fff7d
> contrib: check completionhints file for possible completions
> 
> Check a file called completionhints in the .hg directory for possible completions.
> Each line of this file can be a possible completion. This is useful so we can store
> things like recently viewed hashes in this file and use them for completion, and
> at some point allow us to do bookmark autocompletion without executing hg.

Very interesting.

> diff --git a/contrib/bash_completion b/contrib/bash_completion
> --- a/contrib/bash_completion
> +++ b/contrib/bash_completion
> @@ -54,11 +54,36 @@
>  
>  shopt -s extglob
>  
> +_find_root()
> +{
> +    d=$PWD
> +    while : ; do
> +        if [[ -d "$d/.hg" ]]; then
> +            echo $d
> +            return
> +        fi
> +        [[ "$d" = / ]] && break
> +        d=$(cd -P "$d/.." && echo "$PWD")
> +    done
> +}

This wants to be a patch of its own.

>  _hg_cmd()
>  {
>      HGPLAIN=1 "$hg" "$@" 2>/dev/null
>  }
>  
> +_hg_completionhints()
> +{
> +    local root=$(_find_root)
> +    if [[ -n "$root" ]]; then
> +        local hint_file="$root/.hg/completionhints"
> +        if [ -e "$hint_file" ]; then
> +            local hints=$(cat "$hint_file")
> +            COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$hints' -- "$cur"))
> +        fi
> +    fi
> +}

We probably want to add a parameter to this function to say what type of
hints we want and then tweak the hint filename.

> +
>  _hg_commands()
>  {
>      local commands
> @@ -113,6 +138,7 @@
>      local labels="$(_hg_cmd debugnamecomplete "$cur")"
>      local IFS=$'\n'
>      COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$labels' -- "$cur"))
> +    _hg_completionhints
>  }

How do things get into the hints file? How do we clean the file when it
gets stale?
Gulshan Singh - Sept. 17, 2015, 6:47 p.m.
How the completion hints file gets updated depends on the command being
run and what we're completing, but the general idea is that it's ok for
the file to be stale for some short period of time.

For example, if we want to complete all hashes from all commits shown by
`hg log`, we could add those in to the completion file when the command is
run. As new commits are added, we can either ignore them until the next
log. The idea here is that commands like `hg log` will be run often,
especially when you need to find a hash, so it's ok if new hashes that are
created from commits aren't in the completion file, because they'll get
added on the next `hg log`. A similar thing can be done for bookmarks.

I think one improvement here though is if we have separate files for
separate commands that want to add to the completion hints file. Imagine
if `hg log` wrote to .completionhints.hashes, and then you have some
custom extension that also writes to .completionhints.hashes, then the
previous completions would be overwritten. Another example is if we have
.completionhints.bookmarks and that's written to by `hg log` and `hg
bookmarks`, those two commands could overwrite each other.

What we could do is use .completionhints.hashes.log for `hg log` and
.completionhints.hashes.foo for `hg foo` (some extension). Then the
completion script could  read from .completionhints.hashes.* (and
.completionhints.bookmarks.* for bookmarks).

On 9/16/15, 12:52 PM, "Matt Mackall" <mpm@selenic.com> wrote:

>On Tue, 2015-09-15 at 13:30 -0700, Gulshan Singh wrote:
>> # HG changeset patch
>> # User Gulshan Singh <gulshan@fb.com>
>> # Date 1441845115 25200
>> #      Wed Sep 09 17:31:55 2015 -0700
>> # Node ID 4e3b6c50e59e493d6ef557476f962770787ba3c3
>> # Parent  ab1c6e4efda47281b14a4f5a46cc0d4a114fff7d
>> contrib: check completionhints file for possible completions
>> 
>> Check a file called completionhints in the .hg directory for possible
>>completions.
>> Each line of this file can be a possible completion. This is useful so
>>we can store
>> things like recently viewed hashes in this file and use them for
>>completion, and
>> at some point allow us to do bookmark autocompletion without executing
>>hg.
>
>Very interesting.
>
>> diff --git a/contrib/bash_completion b/contrib/bash_completion
>> --- a/contrib/bash_completion
>> +++ b/contrib/bash_completion
>> @@ -54,11 +54,36 @@
>>  
>>  shopt -s extglob
>>  
>> +_find_root()
>> +{
>> +    d=$PWD
>> +    while : ; do
>> +        if [[ -d "$d/.hg" ]]; then
>> +            echo $d
>> +            return
>> +        fi
>> +        [[ "$d" = / ]] && break
>> +        d=$(cd -P "$d/.." && echo "$PWD")
>> +    done
>> +}
>
>This wants to be a patch of its own.
>
>>  _hg_cmd()
>>  {
>>      HGPLAIN=1 "$hg" "$@" 2>/dev/null
>>  }
>>  
>> +_hg_completionhints()
>> +{
>> +    local root=$(_find_root)
>> +    if [[ -n "$root" ]]; then
>> +        local hint_file="$root/.hg/completionhints"
>> +        if [ -e "$hint_file" ]; then
>> +            local hints=$(cat "$hint_file")
>> +            COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$hints' --
>>"$cur"))
>> +        fi
>> +    fi
>> +}
>
>We probably want to add a parameter to this function to say what type of
>hints we want and then tweak the hint filename.
>
>> +
>>  _hg_commands()
>>  {
>>      local commands
>> @@ -113,6 +138,7 @@
>>      local labels="$(_hg_cmd debugnamecomplete "$cur")"
>>      local IFS=$'\n'
>>      COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$labels' -- "$cur"))
>> +    _hg_completionhints
>>  }
>
>How do things get into the hints file? How do we clean the file when it
>gets stale?
>
>-- 
>Mathematics is the supreme nostalgia of our time.
Durham Goode - Sept. 17, 2015, 7:50 p.m.
On 9/15/15 1:30 PM, Gulshan Singh wrote:
> # HG changeset patch
> # User Gulshan Singh <gulshan@fb.com>
> # Date 1441845115 25200
> #      Wed Sep 09 17:31:55 2015 -0700
> # Node ID 4e3b6c50e59e493d6ef557476f962770787ba3c3
> # Parent  ab1c6e4efda47281b14a4f5a46cc0d4a114fff7d
> contrib: check completionhints file for possible completions
>
> Check a file called completionhints in the .hg directory for possible completions.
> Each line of this file can be a possible completion. This is useful so we can store
> things like recently viewed hashes in this file and use them for completion, and
> at some point allow us to do bookmark autocompletion without executing hg.
>
I've been using this for a couple days, and it's the best thing since 
sliced bread.  If you remove the actual _hg_labels call that execs 
mercurial (which slows things down), it becomes instant hash completion.

We should have a variant of the normal completion that does not exec 
mercurial at all.

Patch

diff --git a/contrib/bash_completion b/contrib/bash_completion
--- a/contrib/bash_completion
+++ b/contrib/bash_completion
@@ -54,11 +54,36 @@ 
 
 shopt -s extglob
 
+_find_root()
+{
+    d=$PWD
+    while : ; do
+        if [[ -d "$d/.hg" ]]; then
+            echo $d
+            return
+        fi
+        [[ "$d" = / ]] && break
+        d=$(cd -P "$d/.." && echo "$PWD")
+    done
+}
+
 _hg_cmd()
 {
     HGPLAIN=1 "$hg" "$@" 2>/dev/null
 }
 
+_hg_completionhints()
+{
+    local root=$(_find_root)
+    if [[ -n "$root" ]]; then
+        local hint_file="$root/.hg/completionhints"
+        if [ -e "$hint_file" ]; then
+            local hints=$(cat "$hint_file")
+            COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$hints' -- "$cur"))
+        fi
+    fi
+}
+
 _hg_commands()
 {
     local commands
@@ -113,6 +138,7 @@ 
     local labels="$(_hg_cmd debugnamecomplete "$cur")"
     local IFS=$'\n'
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$labels' -- "$cur"))
+    _hg_completionhints
 }
 
 # this is "kind of" ugly...