gvfs bash completion
- From: David Zeuthen <david fubar dk>
- To: Alexander Larsson <alexl redhat com>
- Cc: nautilus-list gnome org
- Subject: gvfs bash completion
- Date: Fri, 22 Feb 2008 23:58:54 -0500
Hey,
So here's a simple patch I've been wanting to write for some time. It
provides completion on the URI in bash(1) for the various gvfs-*
commandline tools.
There's also some fixes for gvfs-ls including making -h actually work
(previously hidden files were shown by default) and also a -l option
similar to ls(1) (without it we only print the names; previously we
showed more info).
In [1] is a sample bash session using this.
David
[1] :
[davidz oneill ~]$ gvfs-info
file:/// gphoto2://[usb:001,011]/
file:///media/EOS_DIGITAL sftp://hook.local/
[davidz oneill ~]$ gvfs-info gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_00
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0006.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0007.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0008.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0009.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0010.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0011.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0012.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0013.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0014.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0015.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0016.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0017.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0018.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0019.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0020.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0021.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0022.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0023.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0024.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0025.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0026.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0027.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0028.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0029.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0030.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0031.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0032.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0033.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0034.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0035.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0036.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0037.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0038.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0039.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0040.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0041.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0042.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0043.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0044.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0045.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0046.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0047.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0048.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0049.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0050.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0051.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0052.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0053.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0054.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0055.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0056.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0057.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0058.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0059.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0060.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0061.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0062.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0063.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0064.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0067.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0068.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0069.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0070.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0071.JPG
gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0072.JPG
[davidz oneill ~]$ gvfs-info gphoto2://[usb:001,011]/DCIM/100APPLE/IMG_0072.JPG
display name: IMG_0072.JPG
name: IMG_0072.JPG
type: regular
size: 332791
attributes:
standard::name: IMG_0072.JPG
standard::display-name: IMG_0072.JPG
standard::icon: GThemedIcon:0x8a19c50
standard::type: 1
standard::content-type: image/jpeg
standard::size: 332791
access::can-read: TRUE
access::can-write: FALSE
access::can-delete: FALSE
access::can-execute: FALSE
access::can-trash: FALSE
access::can-rename: FALSE
id::filesystem: host='[usb:001,011]',type='gphoto2',mount_prefix='/'
thumbnail::path: /home/davidz/.thumbnails/normal/dcc65a0b4c80c0339e7600bd68f8af21.png
time::modified: 1202675218
time::modified-usec: 0
Index: programs/gvfs-ls.c
===================================================================
--- programs/gvfs-ls.c (revision 1340)
+++ programs/gvfs-ls.c (working copy)
@@ -1,3 +1,5 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright (C) 2006-2007 Red Hat, Inc.
@@ -29,11 +31,17 @@
static char *attributes = NULL;
static gboolean show_hidden = FALSE;
+static gboolean show_mounts = FALSE;
+static gboolean show_long = FALSE;
+static char *show_completions = NULL;
static GOptionEntry entries[] =
{
{ "attributes", 'a', 0, G_OPTION_ARG_STRING, &attributes, "The attributes to get", NULL },
{ "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, "Show hidden files", NULL },
+ { "long", 'l', 0, G_OPTION_ARG_NONE, &show_long, "Use a long listing format", NULL },
+ { "show-completions", 'c', 0, G_OPTION_ARG_STRING, &show_completions, "Show completions", NULL},
+ { "show-mounts", 'm', 0, G_OPTION_ARG_NONE, &show_mounts, "Show mounts", NULL },
{ NULL }
};
@@ -86,7 +94,14 @@
size = g_file_info_get_size (info);
type = type_to_string (g_file_info_get_file_type (info));
- g_print ("%s\t%"G_GUINT64_FORMAT"\t(%s)", name, (guint64)size, type);
+ if (show_long)
+ {
+ g_print ("%s\t%"G_GUINT64_FORMAT"\t(%s)", name, (guint64)size, type);
+ }
+ else
+ {
+ g_print ("%s", name);
+ }
first_attr = TRUE;
attributes = g_file_info_list_attributes (info, NULL);
@@ -94,9 +109,11 @@
{
char *val_as_string;
- if (strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0 ||
+ if (!show_long ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_NAME) == 0 ||
strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_SIZE) == 0 ||
- strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_TYPE) == 0)
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_TYPE) == 0 ||
+ strcmp (attributes[i], G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) == 0)
continue;
if (first_attr)
@@ -130,7 +147,7 @@
enumerator = g_file_enumerate_children (file, attributes, 0, NULL, &error);
if (enumerator == NULL)
{
- g_print ("Error: %s\n", error->message);
+ g_printerr ("Error: %s\n", error->message);
g_error_free (error);
error = NULL;
return;
@@ -145,19 +162,131 @@
if (error)
{
- g_print ("Error: %s\n", error->message);
+ g_printerr ("Error: %s\n", error->message);
g_error_free (error);
error = NULL;
}
if (!g_file_enumerator_close (enumerator, NULL, &error))
{
- g_print ("Error closing enumerator: %s\n", error->message);
+ g_printerr ("Error closing enumerator: %s\n", error->message);
g_error_free (error);
error = NULL;
}
}
+static void
+print_mounts (const char *prefix)
+{
+ GList *l;
+ GList *mounts;
+ GVolumeMonitor *volume_monitor;
+
+ volume_monitor = g_volume_monitor_get ();
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+ if (mounts != NULL)
+ {
+ for (l = mounts; l != NULL; l = l->next)
+ {
+ GMount *mount = l->data;
+ GFile *mount_root;
+ char *uri;
+
+ mount_root = g_mount_get_root (mount);
+ uri = g_file_get_uri (mount_root);
+ if (prefix == NULL || g_str_has_prefix (uri, prefix))
+ {
+ g_print ("%s\n", uri);
+ }
+ g_free (uri);
+ g_object_unref (mount_root);
+ g_object_unref (mount);
+ }
+ g_list_free (mounts);
+ }
+ g_object_unref (volume_monitor);
+
+ if (prefix == NULL || g_str_has_prefix ("file:///", prefix))
+ {
+ g_print ("file:///\n");
+ }
+}
+
+static void
+print_completions (const char *uri)
+{
+ GFile *f;
+ GFile *parent;
+
+ f = g_file_new_for_uri (uri);
+ if (!g_file_is_native (f))
+ {
+ GMount *mount;
+ mount = g_file_find_enclosing_mount (f, NULL, NULL);
+ if (mount == NULL)
+ {
+ print_mounts (uri);
+ g_object_unref (f);
+ return;
+ }
+ g_object_unref (mount);
+ }
+
+ if (g_str_has_suffix (uri, "/"))
+ {
+ parent = g_object_ref (f);
+ }
+ else
+ {
+ parent = g_file_get_parent (f);
+ }
+
+ if (parent != NULL)
+ {
+ GFileEnumerator *enumerator;
+ enumerator = g_file_enumerate_children (parent,
+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ 0,
+ NULL,
+ NULL);
+ if (enumerator != NULL)
+ {
+ GFileInfo *info;
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL)
+ {
+ const char *name;
+ GFileType type;
+
+ name = g_file_info_get_name (info);
+ type = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
+ if (name != NULL)
+ {
+ GFile *entry;
+ char *entry_uri;
+ entry = g_file_get_child (parent, name);
+ entry_uri = g_file_get_uri (entry);
+ g_object_unref (entry);
+
+ if (g_str_has_prefix (entry_uri, uri))
+ {
+ g_print ("%s", entry_uri);
+ if (type & G_FILE_TYPE_DIRECTORY)
+ {
+ g_print ("/");
+ }
+ g_print ("\n");
+ }
+ g_free (entry_uri);
+ }
+ g_object_unref (info);
+ }
+ g_file_enumerator_close (enumerator, NULL, NULL);
+ }
+ g_object_unref (parent);
+ }
+}
+
int
main (int argc, char *argv[])
{
@@ -175,12 +304,30 @@
g_option_context_parse (context, &argc, &argv, &error);
g_option_context_free (context);
+ if (attributes != NULL)
+ {
+ /* asking for attributes implies -l; otherwise it won't get shown */
+ show_long = TRUE;
+ }
+
attributes = g_strconcat (G_FILE_ATTRIBUTE_STANDARD_NAME ","
G_FILE_ATTRIBUTE_STANDARD_TYPE ","
- G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
attributes != NULL ? "," : "",
attributes,
NULL);
+
+ if (show_mounts)
+ {
+ print_mounts (NULL);
+ return 0;
+ }
+ else if (show_completions != NULL)
+ {
+ print_completions (show_completions);
+ return 0;
+ }
if (argc > 1)
{
Index: programs/Makefile.am
===================================================================
--- programs/Makefile.am (revision 1340)
+++ programs/Makefile.am (working copy)
@@ -30,6 +30,9 @@
gvfs-less \
$(NULL)
+profiledir = $(sysconfdir)/profile.d
+profile_SCRIPTS = gvfs-bash-completion.sh
+
gvfs_cat_SOURCES = gvfs-cat.c
gvfs_cat_LDADD = $(libraries)
--- /dev/null 2008-02-22 11:51:15.646005979 -0500
+++ programs/gvfs-bash-completion.sh 2008-02-22 23:51:15.000000000 -0500
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2007 Red Hat, Inc.
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+# USA.
+#
+# Author: David Zeuthen <davidz redhat com>
+
+# Check for bash
+[ -z "$BASH_VERSION" ] && return
+
+####################################################################################################
+
+# don't misbehave on colons; See item E13 at http://tiswww.case.edu/php/chet/bash/FAQ
+COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
+
+__gvfs_multiple_uris() {
+ local IFS=$'\n'
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+
+ if [ "$cur" = "" ] ; then
+ COMPREPLY=($(compgen -W "$(gvfs-ls --show-mounts)" -- $cur))
+ else
+ COMPREPLY=($(compgen -W "$(gvfs-ls --show-completions $cur)" -- $cur))
+ fi
+}
+
+####################################################################################################
+
+complete -o nospace -F __gvfs_multiple_uris gvfs-ls
+complete -o nospace -F __gvfs_multiple_uris gvfs-info
+complete -o nospace -F __gvfs_multiple_uris gvfs-cat
+complete -o nospace -F __gvfs_multiple_uris gvfs-less
+complete -o nospace -F __gvfs_multiple_uris gvfs-copy
+complete -o nospace -F __gvfs_multiple_uris gvfs-mkdir
+complete -o nospace -F __gvfs_multiple_uris gvfs-monitor-dir
+complete -o nospace -F __gvfs_multiple_uris gvfs-monitor-file
+complete -o nospace -F __gvfs_multiple_uris gvfs-move
+complete -o nospace -F __gvfs_multiple_uris gvfs-open
+complete -o nospace -F __gvfs_multiple_uris gvfs-rm
+complete -o nospace -F __gvfs_multiple_uris gvfs-save
+complete -o nospace -F __gvfs_multiple_uris gvfs-trash
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]