Browse Source

Added option --format, which lets you change the output format. Useful to manually parse variables, and to avoid using eval.

naelstrof 9 years ago
parent
commit
5cc203e18a
6 changed files with 144 additions and 33 deletions
  1. 27
    2
      README.md
  2. 24
    2
      cmdline.c
  3. 5
    1
      cmdline.h
  4. 5
    0
      gengetopt.sh
  5. 70
    27
      main.cpp
  6. 13
    1
      options.ggo

+ 27
- 2
README.md View File

@@ -36,6 +36,20 @@ If you don't like ImageMagick's import: Check out [maim](https://github.com/nael
36 36
 You can see my implementation of slop in a screenshooter here:
37 37
 https://gist.github.com/naelstrof/6530959
38 38
 
39
+For those of you who don't want eval to be an integral part of slop (Could be dangerous if I were evil!): You can change the output format and parse it manually like so:
40
+```bash
41
+#!/bin/bash
42
+slopoutput=$(slop -f "%x %y %w %h %g $i")
43
+X=$(echo $slopoutput | awk '{print $1}')
44
+Y=$(echo $slopoutput | awk '{print $2}')
45
+W=$(echo $slopoutput | awk '{print $3}')
46
+H=$(echo $slopoutput | awk '{print $4}')
47
+G=$(echo $slopoutput | awk '{print $5}')
48
+ID=$(echo $slopoutput | awk '{print $6}')
49
+maim -g $G -i $ID
50
+ffmpeg -f x11grab -s "$W"x"$H" -i :0.0+$X,$Y -f alsa -i pulse ~/myfile.webm
51
+```
52
+
39 53
 ## Lets see some action
40 54
 Ok. Here's a comparison between 'scrot -s's selection and slop's:
41 55
 ![scrotbad](http://farmpolice.com/content/images/2014-10-14-12:08:24.png)
@@ -67,9 +81,10 @@ Make sure to check out and install [maim](https://github.com/naelstrof/maim) too
67 81
 help
68 82
 ----
69 83
 ```text
70
-slop v3.1.5
84
+slop v3.1.7
71 85
 
72
-Copyright (C) 2014 Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors)
86
+Copyright (C) 2014 Dalton Nell, Slop Contributors
87
+(https://github.com/naelstrof/slop/graphs/contributors)
73 88
 
74 89
 Usage: slop [options]
75 90
 
@@ -113,6 +128,9 @@ Options
113 128
                                   highlights it. This is only useful when
114 129
                                   --color is set to a transparent color.
115 130
                                   (default=off)
131
+  -f, --format=STRING           Set the output format string. Format specifiers
132
+                                  are %x, %y, %w, %h, %i, %g, and %c.
133
+                                  (default=`X=%x\nY=%y\nW=%w\nH=%h\nG=%g\nID=%i\nCancel=%c\n')
116 134
 
117 135
 Examples
118 136
     $ # Gray, thick, transparent border for maximum visiblity.
@@ -126,4 +144,11 @@ Examples
126 144
 
127 145
     $ # Classic Windows XP selection.
128 146
     $ slop -l -c 0.3,0.4,0.6,0.4
147
+
148
+    $ # Change output format to use safer parsing
149
+    $ slopoutput=$(slop -f "%x %y %w %h")
150
+    $ X=$(echo $slopoutput | awk '{print $1}')
151
+    $ Y=$(echo $slopoutput | awk '{print $2}')
152
+    $ W=$(echo $slopoutput | awk '{print $3}')
153
+    $ H=$(echo $slopoutput | awk '{print $4}')
129 154
 ```

+ 24
- 2
cmdline.c View File

@@ -48,7 +48,8 @@ const char *gengetopt_args_info_help[] = {
48 48
   "      --min=INT                 Set the minimum output of width or height\n                                  values. This is useful to avoid outputting 0.\n                                  Setting min and max to the same value\n                                  disables drag selections.  (default=`0')",
49 49
   "      --max=INT                 Set the maximum output of width or height\n                                  values. Setting min and max to the same value\n                                  disables drag selections.  (default=`0')",
50 50
   "  -l, --highlight               Instead of outlining selections, slop\n                                  highlights it. This is only useful when\n                                  --color is set to a transparent color.\n                                  (default=off)",
51
-  "\nExamples\n    $ # Gray, thick, transparent border for maximum visiblity.\n    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n\n    $ # Remove window decorations.\n    $ slop --nodecorations\n\n    $ # Disable window selections. Useful for selecting individual pixels.\n    $ slop -t 0\n\n    $ # Classic Windows XP selection.\n    $ slop -l -c 0.3,0.4,0.6,0.4\n",
51
+  "  -f, --format=STRING           Set the output format string. Format specifiers\n                                  are %x, %y, %w, %h, %i, %g, and %c.\n                                  (default=`X=%x\\nY=%y\\nW=%w\\nH=%h\\nG=%g\\nID=%i\\nCancel=%c\\n')",
52
+  "\nExamples\n    $ # Gray, thick, transparent border for maximum visiblity.\n    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n\n    $ # Remove window decorations.\n    $ slop --nodecorations\n\n    $ # Disable window selections. Useful for selecting individual pixels.\n    $ slop -t 0\n\n    $ # Classic Windows XP selection.\n    $ slop -l -c 0.3,0.4,0.6,0.4\n\n    $ # Change output format to use safer parsing\n    $ slopoutput=$(slop -f \"%x %y %w %h\")\n    $ X=$(echo $slopoutput | awk '{print $1}')\n    $ Y=$(echo $slopoutput | awk '{print $2}')\n    $ W=$(echo $slopoutput | awk '{print $3}')\n    $ H=$(echo $slopoutput | awk '{print $4}')\n",
52 53
     0
53 54
 };
54 55
 
@@ -87,6 +88,7 @@ void clear_given (struct gengetopt_args_info *args_info)
87 88
   args_info->min_given = 0 ;
88 89
   args_info->max_given = 0 ;
89 90
   args_info->highlight_given = 0 ;
91
+  args_info->format_given = 0 ;
90 92
 }
91 93
 
92 94
 static
@@ -112,6 +114,8 @@ void clear_args (struct gengetopt_args_info *args_info)
112 114
   args_info->max_arg = 0;
113 115
   args_info->max_orig = NULL;
114 116
   args_info->highlight_flag = 0;
117
+  args_info->format_arg = gengetopt_strdup ("X=%x\nY=%y\nW=%w\nH=%h\nG=%g\nID=%i\nCancel=%c\n");
118
+  args_info->format_orig = NULL;
115 119
   
116 120
 }
117 121
 
@@ -133,6 +137,7 @@ void init_args_info(struct gengetopt_args_info *args_info)
133 137
   args_info->min_help = gengetopt_args_info_help[11] ;
134 138
   args_info->max_help = gengetopt_args_info_help[12] ;
135 139
   args_info->highlight_help = gengetopt_args_info_help[13] ;
140
+  args_info->format_help = gengetopt_args_info_help[14] ;
136 141
   
137 142
 }
138 143
 
@@ -227,6 +232,8 @@ cmdline_parser_release (struct gengetopt_args_info *args_info)
227 232
   free_string_field (&(args_info->color_orig));
228 233
   free_string_field (&(args_info->min_orig));
229 234
   free_string_field (&(args_info->max_orig));
235
+  free_string_field (&(args_info->format_arg));
236
+  free_string_field (&(args_info->format_orig));
230 237
   
231 238
   
232 239
 
@@ -283,6 +290,8 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
283 290
     write_into_file(outfile, "max", args_info->max_orig, 0);
284 291
   if (args_info->highlight_given)
285 292
     write_into_file(outfile, "highlight", 0, 0 );
293
+  if (args_info->format_given)
294
+    write_into_file(outfile, "format", args_info->format_orig, 0);
286 295
   
287 296
 
288 297
   i = EXIT_SUCCESS;
@@ -550,10 +559,11 @@ cmdline_parser_internal (
550 559
         { "min",	1, NULL, 0 },
551 560
         { "max",	1, NULL, 0 },
552 561
         { "highlight",	0, NULL, 'l' },
562
+        { "format",	1, NULL, 'f' },
553 563
         { 0,  0, 0, 0 }
554 564
       };
555 565
 
556
-      c = getopt_long (argc, argv, "hVb:p:t:g:c:nl", long_options, &option_index);
566
+      c = getopt_long (argc, argv, "hVb:p:t:g:c:nlf:", long_options, &option_index);
557 567
 
558 568
       if (c == -1) break;	/* Exit from `while (1)' loop.  */
559 569
 
@@ -649,6 +659,18 @@ cmdline_parser_internal (
649 659
             goto failure;
650 660
         
651 661
           break;
662
+        case 'f':	/* Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c..  */
663
+        
664
+        
665
+          if (update_arg( (void *)&(args_info->format_arg), 
666
+               &(args_info->format_orig), &(args_info->format_given),
667
+              &(local_args_info.format_given), optarg, 0, "X=%x\nY=%y\nW=%w\nH=%h\nG=%g\nID=%i\nCancel=%c\n", ARG_STRING,
668
+              check_ambiguity, override, 0, 0,
669
+              "format", 'f',
670
+              additional_error))
671
+            goto failure;
672
+        
673
+          break;
652 674
 
653 675
         case 0:	/* Long option with no short option */
654 676
           /* Sets the x display..  */

+ 5
- 1
cmdline.h View File

@@ -31,7 +31,7 @@ extern "C" {
31 31
 
32 32
 #ifndef CMDLINE_PARSER_VERSION
33 33
 /** @brief the program version */
34
-#define CMDLINE_PARSER_VERSION "v3.1.5"
34
+#define CMDLINE_PARSER_VERSION "v3.1.7"
35 35
 #endif
36 36
 
37 37
 /** @brief Where the command line options are stored */
@@ -69,6 +69,9 @@ struct gengetopt_args_info
69 69
   const char *max_help; /**< @brief Set the maximum output of width or height values. Setting min and max to the same value disables drag selections. help description.  */
70 70
   int highlight_flag;	/**< @brief Instead of outlining selections, slop highlights it. This is only useful when --color is set to a transparent color. (default=off).  */
71 71
   const char *highlight_help; /**< @brief Instead of outlining selections, slop highlights it. This is only useful when --color is set to a transparent color. help description.  */
72
+  char * format_arg;	/**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. (default='REPLACEME').  */
73
+  char * format_orig;	/**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. original value given at command line.  */
74
+  const char *format_help; /**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. help description.  */
72 75
   
73 76
   unsigned int help_given ;	/**< @brief Whether help was given.  */
74 77
   unsigned int version_given ;	/**< @brief Whether version was given.  */
@@ -83,6 +86,7 @@ struct gengetopt_args_info
83 86
   unsigned int min_given ;	/**< @brief Whether min was given.  */
84 87
   unsigned int max_given ;	/**< @brief Whether max was given.  */
85 88
   unsigned int highlight_given ;	/**< @brief Whether highlight was given.  */
89
+  unsigned int format_given ;	/**< @brief Whether format was given.  */
86 90
 
87 91
 } ;
88 92
 

+ 5
- 0
gengetopt.sh View File

@@ -0,0 +1,5 @@
1
+#!/bin/bash
2
+# This is used because a bug in gengetopt keeps you from putting \n in default string options. All it does is replace REPLACEME with the correct code to make the application work properly.
3
+gengetopt < options.ggo
4
+sed -i '0,/REPLACEME/{s/REPLACEME/X=%x\\\\nY=%y\\\\nW=%w\\\\nH=%h\\\\nG=%g\\\\nID=%i\\\\nCancel=%c\\\\n/}' cmdline.c
5
+sed -i 's/REPLACEME/X=%x\\nY=%y\\nW=%w\\nH=%h\\nG=%g\\nID=%i\\nCancel=%c\\n/' cmdline.c

+ 70
- 27
main.cpp View File

@@ -19,35 +19,77 @@
19 19
  */
20 20
 #include <unistd.h>
21 21
 #include <cstdio>
22
+#include <sstream>
22 23
 #include "x.hpp"
23 24
 #include "rectangle.hpp"
24 25
 #include "cmdline.h"
25 26
 
26
-void printSelection( bool cancelled, int x, int y, int w, int h, int window ) {
27
-    printf( "X=%i\n", x );
28
-    printf( "Y=%i\n", y );
29
-    printf( "W=%i\n", w );
30
-    printf( "H=%i\n", h );
31
-    printf( "G=%ix%i", w, h );
32
-    if ( x >= 0 ) {
33
-        printf( "+%i", x );
34
-    } else {
35
-        // Negative is already included
36
-        printf( "%i", x );
37
-    }
38
-    if ( y >= 0 ) {
39
-        printf( "+%i", y );
40
-    } else {
41
-        // Negative is already included
42
-        printf( "%i", y );
27
+int printSelection( std::string format, bool cancelled, int x, int y, int w, int h, int window ) {
28
+    size_t pos = 0;
29
+    while ( ( pos = format.find( "%", pos ) ) != std::string::npos ) {
30
+        if ( pos + 1 > format.size() ) {
31
+            fprintf( stderr, "Format error: %% found at the end of format string.\n", format[ pos + 1 ] );
32
+            return 1;
33
+        }
34
+        std::stringstream foo;
35
+        switch( format[ pos + 1 ] ) {
36
+            case '%':
37
+                format.replace( pos, 2, "%" );
38
+                pos += 1;
39
+                break;
40
+            case 'x':
41
+            case 'X':
42
+                foo << x;
43
+                format.replace( pos, 2, foo.str() );
44
+                break;
45
+            case 'y':
46
+            case 'Y':
47
+                foo << y;
48
+                format.replace( pos, 2, foo.str() );
49
+                break;
50
+            case 'w':
51
+            case 'W':
52
+                foo << w;
53
+                format.replace( pos, 2, foo.str() );
54
+                break;
55
+            case 'h':
56
+            case 'H':
57
+                foo << h;
58
+                format.replace( pos, 2, foo.str() );
59
+                break;
60
+            case 'g':
61
+            case 'G':
62
+                foo << w << 'x' << h << '+' << x << '+' << y;
63
+                format.replace( pos, 2, foo.str() );
64
+                break;
65
+            case 'i':
66
+            case 'I':
67
+                foo << window;
68
+                format.replace( pos, 2, foo.str() );
69
+                break;
70
+            case 'c':
71
+            case 'C':
72
+                format.replace( pos, 2, cancelled ? "true" : "false" );
73
+                break;
74
+            default:
75
+                fprintf( stderr, "Format error: %%%c is an unknown replacement identifier.\n", format[ pos + 1 ] );
76
+                fprintf( stderr, "Valid replacements: %%x, %%y, %%w, %%h, %%i, %%c, %%.\n" );
77
+                return 1;
78
+                break;
79
+        }
43 80
     }
44
-    printf( "\n" );
45
-    printf( "ID=%i\n", window );
46
-    if ( cancelled ) {
47
-        printf( "Cancel=true\n" );
48
-    } else {
49
-        printf( "Cancel=false\n" );
81
+    pos = 0;
82
+    while ( ( pos = format.find( "\\", pos ) ) != std::string::npos ) {
83
+        if ( pos + 1 > format.size() ) {
84
+            break;
85
+        }
86
+        if ( format[ pos + 1 ] == 'n' ) {
87
+            format.replace( pos, 2, "\n" );
88
+        }
89
+        pos = pos + 1;
50 90
     }
91
+    printf( "%s", format.c_str() );
92
+    return 0;
51 93
 }
52 94
 
53 95
 int parseColor( std::string arg, float* r, float* g, float* b, float* a ) {
@@ -150,18 +192,19 @@ int main( int argc, char** argv ) {
150 192
     int hmem = 0;
151 193
     int minimumsize = options.min_arg;
152 194
     int maximumsize = options.max_arg;
195
+    std::string format = options.format_arg;
153 196
     cmdline_parser_free( &options );
154 197
 
155 198
     // First we set up the x interface and grab the mouse,
156 199
     // if we fail for either we exit immediately.
157 200
     err = xengine->init( xdisplay.c_str() );
158 201
     if ( err ) {
159
-        printSelection( true, 0, 0, 0, 0, None );
202
+        printSelection( format, true, 0, 0, 0, 0, None );
160 203
         return err;
161 204
     }
162 205
     err = xengine->grabCursor( slop::Cross );
163 206
     if ( err ) {
164
-        printSelection( true, 0, 0, 0, 0, None );
207
+        printSelection( format, true, 0, 0, 0, 0, None );
165 208
         return err;
166 209
     }
167 210
     if ( keyboard ) {
@@ -181,7 +224,7 @@ int main( int argc, char** argv ) {
181 224
         double starti = double( start.tv_sec*1000000000L + start.tv_nsec )/1000000000.f;
182 225
         if ( timei - starti > gracetime ) {
183 226
             if ( ( xengine->anyKeyPressed() && keyboard ) || xengine->mouseDown( 3 ) ) {
184
-                printSelection( true, 0, 0, 0, 0, None );
227
+                printSelection( format, true, 0, 0, 0, 0, None );
185 228
                 fprintf( stderr, "User pressed key. Canceled selection.\n" );
186 229
                 state = -1;
187 230
                 running = false;
@@ -309,7 +352,7 @@ int main( int argc, char** argv ) {
309 352
                 // Delete the rectangle, which will remove it from the screen.
310 353
                 delete selection;
311 354
                 // Print the selection :)
312
-                printSelection( false, x, y, w, h, window );
355
+                printSelection( format, false, x, y, w, h, window );
313 356
                 break;
314 357
             }
315 358
         }

+ 13
- 1
options.ggo View File

@@ -1,5 +1,5 @@
1 1
 package "slop"
2
-version "v3.1.5"
2
+version "v3.1.7"
3 3
 usage "slop [options]"
4 4
 description "slop (Select Operation) is an application that queries for a selection from the user and prints the region to stdout."
5 5
 versiontext "Copyright (C) 2014 Dalton Nell, Slop Contributors (https://github.com/naelstrof/slop/graphs/contributors)"
@@ -61,6 +61,11 @@ option "highlight" l "Instead of outlining selections, slop highlights it. This
61 61
     flag
62 62
     off
63 63
 
64
+option "format" f "Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c."
65
+    string
66
+    default="REPLACEME"
67
+    optional
68
+
64 69
 text "\nExamples\n"
65 70
 text "    $ # Gray, thick, transparent border for maximum visiblity.\n"
66 71
 text "    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n"
@@ -73,3 +78,10 @@ text "    $ slop -t 0\n"
73 78
 text "\n"
74 79
 text "    $ # Classic Windows XP selection.\n"
75 80
 text "    $ slop -l -c 0.3,0.4,0.6,0.4\n"
81
+text "\n"
82
+text "    $ # Change output format to use safer parsing\n"
83
+text "    $ slopoutput=$(slop -f \"%x %y %w %h\")\n"
84
+text "    $ X=$(echo $slopoutput | awk '{print $1}')\n"
85
+text "    $ Y=$(echo $slopoutput | awk '{print $2}')\n"
86
+text "    $ W=$(echo $slopoutput | awk '{print $3}')\n"
87
+text "    $ H=$(echo $slopoutput | awk '{print $4}')\n"