Added new hint mode ;Y to yank text description.
authorDaniel Carl <danielcarl@gmx.de>
Mon, 20 Jan 2014 20:29:11 +0000 (21:29 +0100)
committerDaniel Carl <danielcarl@gmx.de>
Mon, 20 Jan 2014 20:32:00 +0000 (21:32 +0100)
doc/vimb.1
src/hints.c
src/hints.js

index f499cd3..5f9a020 100644 (file)
@@ -273,12 +273,16 @@ feature.
 .B ;y
 Yank hint's destination location into primary and secondary clipboard.
 .TP
+.B ;Y
+Yank hint's text description or form text into primary and secondary
+clipboard.
+.TP
 .BI Syntax: " g;{mode}{hint}"
 Start an extended hints mode and stay there until <Esc> is pressed. Like the
 normal hinting except that after a hint is selected, hints remain visible so
 that another one can be selected with the same action as the first. Note that
 the extended hint mode can only be combined with the following hint modes
-\fI;I ;p ;P ;s ;t ;y\fP.
+\fII p P s t y Y\fP.
 .SS Searching
 .TP
 .BI / QUERY ", ?" QUERY
index 9b58bd3..9c254cb 100644 (file)
@@ -194,11 +194,11 @@ gboolean hints_parse_prompt(const char *prompt, char *mode, gboolean *is_gmode)
     gboolean res;
     char pmode = '\0';
 #ifdef FEATURE_QUEUE
-    static char *modes   = "eiIoOpPstTy";
-    static char *g_modes = "IpPsty";
+    static char *modes   = "eiIoOpPstTyY";
+    static char *g_modes = "IpPstyY";
 #else
-    static char *modes   = "eiIoOstTy";
-    static char *g_modes = "Isty";
+    static char *modes   = "eiIoOstTyY";
+    static char *g_modes = "IstyY";
 #endif
 
     if (!prompt) {
@@ -294,6 +294,7 @@ static gboolean call_hints_function(const char *func, int count, JSValueRef para
                 break;
 
             case 'y':
+            case 'Y':
                 a.i = COMMAND_YANK_ARG;
                 a.s = v;
                 command_yank(&a);
index d4e6fa3..ec49a29 100644 (file)
@@ -108,6 +108,7 @@ Object.freeze((function(){
             offsets.right  = win.innerWidth  - offsets.right;
             offsets.bottom = win.innerHeight - offsets.bottom;
 
+            /* checks if given elemente is in viewport and visible */
             function isVisible(e) {
                 if (typeof e == "undefined") {
                     return false;
@@ -344,29 +345,15 @@ Object.freeze((function(){
             return "ERROR:";
         }
 
-        var e    = activeHint.e,
-            tag  = e.nodeName.toLowerCase(),
-            type = e.type || "",
-            res  = "";
+        var e = activeHint.e,
+            res;
 
-        if (tag === "input" || tag === "textarea" || tag === "select") {
-            if (type === "radio" || type === "checkbox") {
-                e.focus();
-                click(e);
-                res = "DONE:";
-            } else if (type === "submit" || type === "reset" || type  === "button" || type === "image") {
-                click(e);
-                res = "DONE:";
-            } else {
-                e.focus();
-                res = "INSERT:";
-            }
-        } else if (tag === "iframe" || tag === "frame") {
-            e.focus();
-            res = "DONE:";
+        /* process form actions like focus toggling inputs */
+        if (config.handleForm) {
+            res = handleForm(e);
         }
 
-        if (config.continue) {
+        if (config.keepOpen) {
             /* reset the filter number */
             filterNum = 0;
             show(false);
@@ -377,6 +364,30 @@ Object.freeze((function(){
         return res || config.action(e);
     }
 
+    /* focus or toggle form fields */
+    function handleForm(e) {
+        var tag  = e.nodeName.toLowerCase(),
+            type = e.type || "";
+
+        if (tag === "input" || tag === "textarea" || tag === "select") {
+            if (type === "radio" || type === "checkbox") {
+                e.focus();
+                click(e);
+                return "DONE:";
+            }
+            if (type === "submit" || type === "reset" || type  === "button" || type === "image") {
+                click(e);
+                return "DONE:";
+            }
+            e.focus();
+            return "INSERT:";
+        }
+        if (tag === "iframe" || tag === "frame") {
+            e.focus();
+            return "DONE:";
+        }
+    }
+
     /* internal used methods */
     function open(e, newWin) {
         var oldTarget = e.target;
@@ -502,7 +513,7 @@ Object.freeze((function(){
             var prop,
                 /* holds the xpaths for the different modes */
                 xpathmap = {
-                    ot    "//*[@href] | //*[@onclick or @tabindex or @class='lk' or @role='link' or @role='button'] | //input[not(@type='hidden' or @disabled or @readonly)] | //textarea[not(@disabled or @readonly)] | //button | //select",
+                    otY:    "//*[@href] | //*[@onclick or @tabindex or @class='lk' or @role='link' or @role='button'] | //input[not(@type='hidden' or @disabled or @readonly)] | //textarea[not(@disabled or @readonly)] | //button | //select",
                     e:      "//input[not(@type) or @type='text'] | //textarea",
                     iI:     "//img[@src]",
                     OpPsTy: "//*[@href] | //img[@src and not(ancestor::a)] | //iframe[@src]"
@@ -511,12 +522,17 @@ Object.freeze((function(){
                 actionmap = {
                     o:         function(e) {open(e, false); return "DONE:";},
                     t:         function(e) {open(e, true); return "DONE:";},
-                    eiIOpPsTy: function(e) {return "DATA:" + getSrc(e);}
+                    eiIOpPsTy: function(e) {return "DATA:" + getSrc(e);},
+                    Y:         function(e) {return "DATA:" + (e.textContent || "");}
                 };
 
             config = {
-                maxHints: maxHints,
-                continue: keepOpen
+                maxHints:   maxHints,
+                keepOpen:   keepOpen,
+                /* handle forms only useful when there are form fields in xpath */
+                /* don't handle form for Y to allow to yank form filed content */
+                /* instead of switching to input mode */
+                handleForm: ("eot".indexOf(mode) >= 0)
             };
             for (prop in xpathmap) {
                 if (prop.indexOf(mode) >= 0) {