ctioga2 0.9 → 0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Changelog +27 -0
- data/bin/ct2-make-movie +92 -45
- data/lib/ctioga2/commands/doc/html.rb +1 -1
- data/lib/ctioga2/commands/doc/introspection.rb +52 -0
- data/lib/ctioga2/commands/doc/markup.rb +4 -0
- data/lib/ctioga2/commands/general-commands.rb +19 -0
- data/lib/ctioga2/commands/general-functions.rb +8 -1
- data/lib/ctioga2/commands/general-types.rb +14 -3
- data/lib/ctioga2/commands/parsers/file.rb +20 -3
- data/lib/ctioga2/data/backends/backends/math.rb +1 -1
- data/lib/ctioga2/data/backends/backends/text.rb +3 -3
- data/lib/ctioga2/data/point.rb +1 -1
- data/lib/ctioga2/graphics/elements.rb +1 -0
- data/lib/ctioga2/graphics/elements/curve2d.rb +5 -0
- data/lib/ctioga2/graphics/elements/primitive.rb +16 -14
- data/lib/ctioga2/graphics/elements/style-lists.rb +353 -0
- data/lib/ctioga2/graphics/elements/subplot.rb +17 -2
- data/lib/ctioga2/graphics/elements/tangent.rb +16 -17
- data/lib/ctioga2/graphics/styles.rb +1 -0
- data/lib/ctioga2/graphics/styles/axes.rb +63 -0
- data/lib/ctioga2/graphics/styles/base.rb +13 -0
- data/lib/ctioga2/graphics/styles/colorbrewer.rb +316 -0
- data/lib/ctioga2/graphics/styles/colormap.rb +47 -7
- data/lib/ctioga2/graphics/styles/image.rb +83 -0
- data/lib/ctioga2/graphics/styles/plot.rb +43 -7
- data/lib/ctioga2/graphics/styles/sets.rb +47 -5
- data/lib/ctioga2/graphics/styles/sheet.rb +18 -3
- data/lib/ctioga2/graphics/styles/texts.rb +49 -8
- data/lib/ctioga2/graphics/subplot-commands.rb +13 -13
- data/lib/ctioga2/graphics/types.rb +42 -10
- data/lib/ctioga2/graphics/types/boundaries.rb +3 -2
- data/lib/ctioga2/graphics/types/boxes.rb +13 -0
- data/lib/ctioga2/graphics/types/dimensions.rb +4 -1
- data/lib/ctioga2/graphics/types/location.rb +13 -2
- data/lib/ctioga2/graphics/types/point.rb +86 -0
- data/lib/ctioga2/metabuilder/types/styles.rb +2 -2
- data/lib/ctioga2/plotmaker.rb +3 -0
- data/lib/ctioga2/ruby.rb +49 -0
- data/lib/ctioga2/utils.rb +34 -0
- data/lib/ctioga2/version.rb +2 -2
- metadata +8 -4
    
        data/Changelog
    CHANGED
    
    | @@ -1,3 +1,30 @@ | |
| 1 | 
            +
            ctioga2 (0.10)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              * A draw-image function to include JPEG and PNG images
         | 
| 4 | 
            +
              * Axes at origin (with at_x_origin and at_y_origin)
         | 
| 5 | 
            +
              * A drawing-frame command to have pure drawing frames (no axes, 
         | 
| 6 | 
            +
                no labels + coordinates given by physical units)
         | 
| 7 | 
            +
              * A $(point index ...) returning the index of the dataset point
         | 
| 8 | 
            +
              * Commands for drawing the currently available style items (colors,
         | 
| 9 | 
            +
                markers, line styles and sets)
         | 
| 10 | 
            +
              * Inline Ruby code in command files and running of external Ruby code
         | 
| 11 | 
            +
                (for function definition only, since data processing/plotting is not
         | 
| 12 | 
            +
                yet available on the Ruby side)
         | 
| 13 | 
            +
              * Auto sizing of titles and labels
         | 
| 14 | 
            +
              * Alignment for texts with a given width
         | 
| 15 | 
            +
              * Smarter collision detection: now labels stick out of the graph only if
         | 
| 16 | 
            +
                you really ask for it !
         | 
| 17 | 
            +
              * Color sets from colorbrewer2.org
         | 
| 18 | 
            +
              * Improved color maps specifications, including the possibility to
         | 
| 19 | 
            +
                specify color sets as color maps
         | 
| 20 | 
            +
              * A --list-styles command to list (the names of) all stylistic things
         | 
| 21 | 
            +
                (and in particular, defined sets)
         | 
| 22 | 
            +
              * Symmetric color maps
         | 
| 23 | 
            +
              * Various bug fixes and documentation updates
         | 
| 24 | 
            +
              * [ct2-make-movie] multiple outputs at once
         | 
| 25 | 
            +
             | 
| 26 | 
            +
             -- Vincent <vincent.fourmond@9online.fr>  Sun 16 Mar 18:16:01 CET 2014
         | 
| 27 | 
            +
             | 
| 1 28 | 
             
            ctioga2 (0.9)
         | 
| 2 29 |  | 
| 3 30 | 
             
              * A --set command to set variable values from the command-line
         | 
    
        data/bin/ct2-make-movie
    CHANGED
    
    | @@ -34,7 +34,55 @@ ct2 = "ctioga2" | |
| 34 34 |  | 
| 35 35 |  | 
| 36 36 | 
             
            tmpdir = "tmp"
         | 
| 37 | 
            -
             | 
| 37 | 
            +
             | 
| 38 | 
            +
             | 
| 39 | 
            +
            # The class in charge of running ffmpeg
         | 
| 40 | 
            +
            class EncodingJob
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              # Target file
         | 
| 43 | 
            +
              attr_accessor :target
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              # Bitrate
         | 
| 46 | 
            +
              attr_accessor :bitrate
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              # Video codec
         | 
| 49 | 
            +
              attr_accessor :codec
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              # Extra arguments
         | 
| 52 | 
            +
              attr_accessor :extra_args
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              # Writes the given frame for encoding
         | 
| 55 | 
            +
              def write_frame(data)
         | 
| 56 | 
            +
                @encoder.write(data)
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              def add_args(args)
         | 
| 60 | 
            +
                @extra_args ||= []
         | 
| 61 | 
            +
                @extra_args += args
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              # Start job
         | 
| 65 | 
            +
              def start_job(size)
         | 
| 66 | 
            +
                ffmpeg_args = ["ffmpeg", '-y', "-f", "rawvideo", 
         | 
| 67 | 
            +
                               "-r", "25", "-s", size, "-i", "-"]
         | 
| 68 | 
            +
                if @bitrate
         | 
| 69 | 
            +
                  ffmpeg_args << "-b" << @bitrate
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
                if @codec
         | 
| 72 | 
            +
                  ffmpeg_args << "-vcodec" << @codec
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                ffmpeg_args += @extra_args if @extra_args
         | 
| 76 | 
            +
                ffmpeg_args << @target
         | 
| 77 | 
            +
                p ffmpeg_args
         | 
| 78 | 
            +
                @encoder = IO::popen(ffmpeg_args, "wb")
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              def close()
         | 
| 82 | 
            +
                @encoder.close
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
            end
         | 
| 85 | 
            +
             | 
| 38 86 |  | 
| 39 87 | 
             
            DimensionConversion = {
         | 
| 40 88 | 
             
              "pt" => (72.0/72.27),
         | 
| @@ -86,35 +134,56 @@ use_pdftoppm = false | |
| 86 134 | 
             
            # file over and over again.
         | 
| 87 135 | 
             
            store_all = true
         | 
| 88 136 |  | 
| 89 | 
            -
            # Codec for ffmpeg
         | 
| 90 | 
            -
            codec = nil
         | 
| 91 137 |  | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 138 | 
            +
            encoders = [ EncodingJob.new ]
         | 
| 139 | 
            +
            cur_enc = encoders.first
         | 
| 140 | 
            +
             | 
| 94 141 |  | 
| 95 | 
            -
            fargs = []
         | 
| 96 142 | 
             
            opts = OptionParser.new do |opts|
         | 
| 97 143 | 
             
              opts.banner = "Usage: #$0 [options] file.ct2 arguments..."
         | 
| 98 144 |  | 
| 145 | 
            +
              ##################################################
         | 
| 146 | 
            +
              # Encoding-related options
         | 
| 99 147 | 
             
              opts.on("-t", "--target FILE", "Target video file") do |t|
         | 
| 100 | 
            -
                target | 
| 148 | 
            +
                if cur_enc.target
         | 
| 149 | 
            +
                  cur_enc = EncodingJob.new
         | 
| 150 | 
            +
                  encoders << cur_enc
         | 
| 151 | 
            +
                end
         | 
| 152 | 
            +
                cur_enc.target = t
         | 
| 153 | 
            +
              end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              opts.on("-b", "--bitrate RATE", "Bitrate (indicative)") do |v|
         | 
| 156 | 
            +
                cur_enc.bitrate = v
         | 
| 157 | 
            +
              end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
              opts.on("", "--codec CODEC", "Target codec") do |v|
         | 
| 160 | 
            +
                cur_enc.codec = v
         | 
| 161 | 
            +
              end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
              opts.on("", "--ffmpeg-args ARGS", "Extra ffmpeg args") do |v|
         | 
| 164 | 
            +
                 cur_enc.add_args(Shellwords.split(v))
         | 
| 101 165 | 
             
              end
         | 
| 102 166 |  | 
| 167 | 
            +
             | 
| 168 | 
            +
              ##################################################
         | 
| 169 | 
            +
              # 
         | 
| 170 | 
            +
             | 
| 103 171 | 
             
              opts.on("", "--dir DIR", "Temporary directory for storage") do |t|
         | 
| 104 172 | 
             
                tmpdir = t
         | 
| 105 173 | 
             
              end
         | 
| 106 174 |  | 
| 107 175 | 
             
              opts.on("", "--version", "Prints version string") do 
         | 
| 108 | 
            -
                puts "0. | 
| 176 | 
            +
                puts "0.1"
         | 
| 109 177 | 
             
              end
         | 
| 110 178 |  | 
| 111 179 | 
             
              opts.on("-p", "--[no-]pdftoppm", "Whether or not to use pdftoppm") do |t|
         | 
| 112 180 | 
             
                use_pdftoppm = t
         | 
| 113 181 | 
             
              end
         | 
| 114 182 |  | 
| 115 | 
            -
              opts.on("", "--page-size SIZE", 
         | 
| 183 | 
            +
              opts.on("-r", "--page-size SIZE", 
         | 
| 116 184 | 
             
                      "Set ctioga2 page size (in TeX dimensions)") do |v|
         | 
| 117 185 | 
             
                ct2_size = page_size_to_points(v)
         | 
| 186 | 
            +
                p ct2_size
         | 
| 118 187 | 
             
              end
         | 
| 119 188 |  | 
| 120 189 | 
             
              opts.on("", "--resolution RES",
         | 
| @@ -127,17 +196,6 @@ opts = OptionParser.new do |opts| | |
| 127 196 | 
             
                store_all = v
         | 
| 128 197 | 
             
              end
         | 
| 129 198 |  | 
| 130 | 
            -
              opts.on("-b", "--bitrate RATE", "Bitrate (indicative)") do |v|
         | 
| 131 | 
            -
                bitrate = v
         | 
| 132 | 
            -
              end
         | 
| 133 | 
            -
             | 
| 134 | 
            -
              opts.on("", "--codec CODEC", "Target codec") do |v|
         | 
| 135 | 
            -
                codec = v
         | 
| 136 | 
            -
              end
         | 
| 137 | 
            -
             | 
| 138 | 
            -
              opts.on("", "--ffmpeg-args ARGS", "Extra ffmpeg args") do |v|
         | 
| 139 | 
            -
                fargs += Shellwords.split(v)
         | 
| 140 | 
            -
              end
         | 
| 141 199 |  | 
| 142 200 | 
             
            end
         | 
| 143 201 |  | 
| @@ -160,7 +218,7 @@ puts "Producing #{ct2_page_size} PDF and converting to #{size} for the video" | |
| 160 218 |  | 
| 161 219 |  | 
| 162 220 | 
             
            file = ARGV.shift
         | 
| 163 | 
            -
            target ||= file.sub(/(\.ct2)?$/, ".avi")
         | 
| 221 | 
            +
            cur_enc.target ||= file.sub(/(\.ct2)?$/, ".avi")
         | 
| 164 222 | 
             
            args = []
         | 
| 165 223 |  | 
| 166 224 | 
             
            for a in ARGV
         | 
| @@ -184,22 +242,12 @@ FileUtils::mkpath(tmpdir) | |
| 184 242 |  | 
| 185 243 |  | 
| 186 244 | 
             
            # @todo Use other encoding programs !
         | 
| 187 | 
            -
            # @todo bitrate control
         | 
| 188 245 |  | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
              ffmpeg_args << "-b" << bitrate
         | 
| 193 | 
            -
            end
         | 
| 194 | 
            -
            if codec
         | 
| 195 | 
            -
              ffmpeg_args << "-vcodec" << codec
         | 
| 246 | 
            +
            # Start all encoders
         | 
| 247 | 
            +
            for enc in encoders
         | 
| 248 | 
            +
              enc.start_job(size)
         | 
| 196 249 | 
             
            end
         | 
| 197 250 |  | 
| 198 | 
            -
            ffmpeg_args += fargs
         | 
| 199 | 
            -
            ffmpeg_args << target
         | 
| 200 | 
            -
             | 
| 201 | 
            -
            encoder = IO::popen(ffmpeg_args, "wb")
         | 
| 202 | 
            -
             | 
| 203 251 | 
             
            format = if store_all 
         | 
| 204 252 | 
             
                       "#{tmpdir}/file-%04d"
         | 
| 205 253 | 
             
                     else
         | 
| @@ -218,36 +266,35 @@ for f in args | |
| 218 266 | 
             
              puts "Running: #{ct2_cmdline.join(" ")}"
         | 
| 219 267 | 
             
              system(*ct2_cmdline)
         | 
| 220 268 |  | 
| 269 | 
            +
              b = nil
         | 
| 270 | 
            +
             | 
| 221 271 | 
             
              if use_pdftoppm
         | 
| 222 | 
            -
                # @todo use other conversion programs !
         | 
| 223 272 | 
             
                b1, s = Open3.capture2(
         | 
| 224 273 | 
             
                                      "pdftoppm",
         | 
| 225 274 | 
             
                                      "-r",
         | 
| 226 275 | 
             
                                      "#{(conv*oversampling).to_i}",
         | 
| 227 276 | 
             
                                       "#{name}.pdf",
         | 
| 228 277 | 
             
                                      :stdin_data=>"", :binmode=>true)
         | 
| 229 | 
            -
                # @todo use other conversion programs !
         | 
| 230 278 | 
             
                b, s = Open3.capture2("convert",
         | 
| 231 279 | 
             
                                      "PPM:-",
         | 
| 232 | 
            -
                                      "-resize", size,
         | 
| 280 | 
            +
                                      "-resize", "#{size}!",
         | 
| 233 281 | 
             
                                      "-depth", "8", "YUV:-",
         | 
| 234 282 | 
             
                                      :stdin_data=>b1, :binmode=>true)
         | 
| 235 283 | 
             
              else
         | 
| 236 | 
            -
                
         | 
| 237 | 
            -
                # @todo use other conversion programs !
         | 
| 238 284 | 
             
                b, s = Open3.capture2("convert",
         | 
| 239 285 | 
             
                                      "-density", "#{(conv*oversampling).to_i}",
         | 
| 240 286 | 
             
                                      "#{name}.pdf",
         | 
| 241 287 | 
             
                                      "-alpha", "Remove",
         | 
| 242 | 
            -
                                      "-resize", size,
         | 
| 288 | 
            +
                                      "-resize", "#{size}!",
         | 
| 243 289 | 
             
                                      "-depth", "8", "YUV:-",
         | 
| 244 290 | 
             
                                      :stdin_data=>"", :binmode=>true)
         | 
| 245 | 
            -
                
         | 
| 246 | 
            -
                # Use pdftoppm followed by convert, much much faster than just
         | 
| 247 | 
            -
                # convert (gs takes too much time)
         | 
| 248 291 | 
             
              end
         | 
| 249 | 
            -
               | 
| 292 | 
            +
              for enc in encoders
         | 
| 293 | 
            +
                enc.write_frame(b)
         | 
| 294 | 
            +
              end
         | 
| 250 295 | 
             
              index += 1
         | 
| 251 296 | 
             
            end
         | 
| 252 297 |  | 
| 253 | 
            -
             | 
| 298 | 
            +
            for enc in encoders
         | 
| 299 | 
            +
              enc.close
         | 
| 300 | 
            +
            end
         | 
| @@ -303,7 +303,7 @@ module CTioga2 | |
| 303 303 | 
             
                          when String       # plain URL target
         | 
| 304 304 | 
             
                            link = "#{it.target}"
         | 
| 305 305 | 
             
                          else
         | 
| 306 | 
            -
                            raise "The link target should be either a group, a command or a type, but is a #{it.target.class}"
         | 
| 306 | 
            +
                            raise "The link target should be either a group, a command or a type, but is a #{it.target.class} (#{it.dbg.inspect})"
         | 
| 307 307 | 
             
                          end
         | 
| 308 308 | 
             
                          str << "<a href='#{link}'>#{it.to_s}</a>"
         | 
| 309 309 | 
             
                        when MarkedUpText::MarkupItemize
         | 
| @@ -128,6 +128,47 @@ module CTioga2 | |
| 128 128 | 
             
                      end
         | 
| 129 129 | 
             
                    end
         | 
| 130 130 |  | 
| 131 | 
            +
                    # Lists all the stylistic things, and in particular the names
         | 
| 132 | 
            +
                    # of color sets, marker sets and the like.
         | 
| 133 | 
            +
                    #
         | 
| 134 | 
            +
                    # This function will hold more data with time.
         | 
| 135 | 
            +
                    def list_styles
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                      puts "Available color sets:"
         | 
| 138 | 
            +
                      sets = Graphics::Styles::CurveStyleFactory::parameters['line_color'].sets
         | 
| 139 | 
            +
                      set_names = sets.keys.sort
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                      sets_by_prefix = Utils.group_by_prefix(set_names, /(.*?)\d+$/)
         | 
| 142 | 
            +
             | 
| 143 | 
            +
             | 
| 144 | 
            +
                      for pref in sets_by_prefix.keys.sort
         | 
| 145 | 
            +
                        vals = Utils.suffix_numeric_sort(sets_by_prefix[pref])
         | 
| 146 | 
            +
                        puts " * #{vals.join(", ")} "
         | 
| 147 | 
            +
                      end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                      puts "\nAvailable marker sets:"
         | 
| 150 | 
            +
                      sets = Graphics::Styles::CurveStyleFactory::parameters['marker_marker'].sets
         | 
| 151 | 
            +
                      set_names = sets.keys.sort
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                      sets_by_prefix = Utils.group_by_prefix(set_names, /(.*?)\d+$/)
         | 
| 154 | 
            +
                      for pref in sets_by_prefix.keys.sort
         | 
| 155 | 
            +
                        vals = Utils.suffix_numeric_sort(sets_by_prefix[pref])
         | 
| 156 | 
            +
                        puts " * #{vals.join(", ")} "
         | 
| 157 | 
            +
                      end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                      puts "\nAvailable line style sets:"
         | 
| 160 | 
            +
                      sets = Graphics::Styles::CurveStyleFactory::parameters['line_style'].sets
         | 
| 161 | 
            +
                      set_names = sets.keys.sort
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                      sets_by_prefix = Utils.group_by_prefix(set_names, /(.*?)\d+$/)
         | 
| 164 | 
            +
                      for pref in sets_by_prefix.keys.sort
         | 
| 165 | 
            +
                        vals = Utils.suffix_numeric_sort(sets_by_prefix[pref])
         | 
| 166 | 
            +
                        puts " * #{vals.join(", ")} "
         | 
| 167 | 
            +
                      end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
             | 
| 170 | 
            +
                    end
         | 
| 171 | 
            +
             | 
| 131 172 |  | 
| 132 173 | 
             
                    protected 
         | 
| 133 174 |  | 
| @@ -200,6 +241,17 @@ EOH | |
| 200 241 | 
             
                  ListTypesCmd.describe("List known types",
         | 
| 201 242 | 
             
                                         <<EOH, IntrospectionGroup)
         | 
| 202 243 | 
             
            List all types known to ctioga2
         | 
| 244 | 
            +
            EOH
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                  ListStylesCmd = 
         | 
| 247 | 
            +
                    Cmd.new('list-styles', nil, '--list-styles',
         | 
| 248 | 
            +
                            [], RawOption) do |p, opts|
         | 
| 249 | 
            +
                    Introspection.new.list_styles()
         | 
| 250 | 
            +
                  end
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                  ListStylesCmd.describe("List stylistic information",
         | 
| 253 | 
            +
                                         <<EOH, IntrospectionGroup)
         | 
| 254 | 
            +
            Lists all available color sets, marker sets and the like.
         | 
| 203 255 | 
             
            EOH
         | 
| 204 256 |  | 
| 205 257 | 
             
                  EditCommandCmd = 
         | 
| @@ -106,11 +106,15 @@ module CTioga2 | |
| 106 106 | 
             
                    class MarkupLink < MarkupItem
         | 
| 107 107 | 
             
                      # The object target of the link
         | 
| 108 108 | 
             
                      attr_accessor :target
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                      # For error reporting
         | 
| 111 | 
            +
                      attr_reader :dbg
         | 
| 109 112 |  | 
| 110 113 | 
             
                      # _target_ is the name of the target, which can be of _type_
         | 
| 111 114 | 
             
                      # 'group', 'command', 'backend', 'type', 'function' and 'url'
         | 
| 112 115 | 
             
                      def initialize(doc, target, type)
         | 
| 113 116 | 
             
                        super(doc)
         | 
| 117 | 
            +
                        @dbg = [target, type]
         | 
| 114 118 | 
             
                        if type =~ /url/
         | 
| 115 119 | 
             
                          @target = target
         | 
| 116 120 | 
             
                        else
         | 
| @@ -87,6 +87,25 @@ EOH | |
| 87 87 | 
             
            Runs the given strings as commands, as if given from a command file.
         | 
| 88 88 | 
             
            EOH
         | 
| 89 89 |  | 
| 90 | 
            +
             | 
| 91 | 
            +
                # Runs a ruby file
         | 
| 92 | 
            +
                RunRubyFile = 
         | 
| 93 | 
            +
                  Cmd.new("ruby-run", nil, "--ruby-run", 
         | 
| 94 | 
            +
                          [ CmdArg.new('file')], 
         | 
| 95 | 
            +
                          {}
         | 
| 96 | 
            +
                          ) do |plotmaker, file, opts|
         | 
| 97 | 
            +
                  # Work around bug on windows !
         | 
| 98 | 
            +
                  file = Utils::transcode_until_found(file)
         | 
| 99 | 
            +
                  Ruby::run_file(file)
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
                
         | 
| 102 | 
            +
                RunRubyFile.describe("Run as Ruby code", <<EOH, GeneralGroup)
         | 
| 103 | 
            +
            Reads the file and runs the Ruby code found inside, a bit like
         | 
| 104 | 
            +
            Ruby would do with the @require@ command, excepted that @ctioga2@
         | 
| 105 | 
            +
            does not follow Ruby's file searching rules: you have to specify the
         | 
| 106 | 
            +
            full path.
         | 
| 107 | 
            +
            EOH
         | 
| 108 | 
            +
             | 
| 90 109 | 
             
                # Evaluate a series of commands.
         | 
| 91 110 | 
             
                SetCommand =  Cmd.new("set", nil, "--set", 
         | 
| 92 111 | 
             
                                      [ CmdArg.new('text'), 
         | 
| @@ -19,7 +19,7 @@ module CTioga2 | |
| 19 19 | 
             
              module Commands
         | 
| 20 20 |  | 
| 21 21 | 
             
                FuncEval = Function.new("eval", "Evaluate Ruby code") do |pm, code|
         | 
| 22 | 
            -
                   | 
| 22 | 
            +
                  Ruby::run_code(code)
         | 
| 23 23 | 
             
                end
         | 
| 24 24 |  | 
| 25 25 | 
             
                FuncEval.describe <<EOD
         | 
| @@ -35,6 +35,10 @@ They have no type. In particular, while this will work: | |
| 35 35 | 
             
            # b := $(eval $(a) * 3)
         | 
| 36 36 | 
             
            # # b is now 9
         | 
| 37 37 |  | 
| 38 | 
            +
            However, you need to use quotes if you must call functions:
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            # b := $(eval sqrt(2))
         | 
| 41 | 
            +
             | 
| 38 42 | 
             
            Doing the same kind of things with text will be somewhat not satisfying:
         | 
| 39 43 |  | 
| 40 44 | 
             
            # a := "two words"
         | 
| @@ -65,6 +69,8 @@ EOD | |
| 65 69 | 
             
                    point.y.to_s
         | 
| 66 70 | 
             
                  when "xy", "XY"
         | 
| 67 71 | 
             
                    "%g,%g" % point.point
         | 
| 72 | 
            +
                  when "index", "idx"
         | 
| 73 | 
            +
                    point.index
         | 
| 68 74 | 
             
                  else
         | 
| 69 75 | 
             
                    # The \ are not strictly speaking necessary, but they make
         | 
| 70 76 | 
             
                    # ruby-mode happier
         | 
| @@ -82,6 +88,7 @@ dataset. Run this way: | |
| 82 88 |  | 
| 83 89 | 
             
            The first argument, here @x@ tells what we want to know about the
         | 
| 84 90 | 
             
            given point: its @x@ value (passing @x@), its @y@ value (passing @y@),
         | 
| 91 | 
            +
            its @index@ (by passing @index@ or @idx@)
         | 
| 85 92 | 
             
            both its @x@ and @y@ ready to be used as coordinates for drawing
         | 
| 86 93 | 
             
            commands using @xy@. For instance, to draw a circle marker right in
         | 
| 87 94 | 
             
            the middle of the last dataset plotted, just run
         | 
| @@ -121,14 +121,25 @@ EOD | |
| 121 121 |  | 
| 122 122 | 
             
                # A color map
         | 
| 123 123 | 
             
                ColorMapType = CmdType.new('colormap', :colormap, <<EOD)
         | 
| 124 | 
            -
            A Z color map
         | 
| 124 | 
            +
            A Z color map. It takes the form @Color1--Color2--Color3...@. All
         | 
| 125 | 
            +
            colors can optionally be followed by a number. For instance, for
         | 
| 126 | 
            +
            @Red--Blue--Pink--Green@, the colors are evenly spaced. In the case
         | 
| 127 | 
            +
            @Red--Blue(0.1)--Pink(0.2)--Green@, the Blue to Pink strech is located
         | 
| 128 | 
            +
            between Z values 0.1 and 0.2.
         | 
| 125 129 |  | 
| 126 | 
            -
             | 
| 130 | 
            +
            If a prefix @hls:@ or @wheel:@ is present, then linear interpolation
         | 
| 131 | 
            +
            is done in the HLS colorspace instead of the RGB one (the default).
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            If a suffix @:sym:@_value_ is present, then the colormap is symmetric
         | 
| 134 | 
            +
            around that value.
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            It is also possible to directly use a {type: color-set}, in which case
         | 
| 137 | 
            +
            eveything works as if the colors of the {type: color-set} had been
         | 
| 138 | 
            +
            given directly, without Z values.
         | 
| 127 139 | 
             
            EOD
         | 
| 128 140 |  | 
| 129 141 | 
             
                # This ones get here since they mess up with syntax highlighting
         | 
| 130 142 |  | 
| 131 | 
            -
             | 
| 132 143 | 
             
                # A stored dataset.
         | 
| 133 144 | 
             
                StoredDatasetType = CmdType.new('stored-dataset', 
         | 
| 134 145 | 
             
                                                :string, <<EOD)
         | 
| @@ -71,6 +71,7 @@ module CTioga2 | |
| 71 71 | 
             
                      idx = 0
         | 
| 72 72 |  | 
| 73 73 |  | 
| 74 | 
            +
                      has_ruby = false
         | 
| 74 75 | 
             
                      ## @todo line counting ?
         | 
| 75 76 | 
             
                      for l in lines
         | 
| 76 77 | 
             
                        idx += 1
         | 
| @@ -81,8 +82,10 @@ module CTioga2 | |
| 81 82 | 
             
                        ## or make it more accurate ? The problem is that in a
         | 
| 82 83 | 
             
                        ## large command file, there may be things that look like
         | 
| 83 84 | 
             
                        ## old style commands ?
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                        if l =~  | 
| 85 | 
            +
             | 
| 86 | 
            +
                        if l =~ /^\s*ruby\s*$/
         | 
| 87 | 
            +
                          has_ruby = true
         | 
| 88 | 
            +
                        elsif l =~ /^([a-z0-9-]+)\(/ && (!has_ruby)
         | 
| 86 89 | 
             
                          path = io.respond_to?(:path) ? io.path : io.to_s
         | 
| 87 90 | 
             
                          warn { "Found old style (deprecated) commands in '#{path}', using old style parser"}
         | 
| 88 91 | 
             
                          return OldFileParser.new.
         | 
| @@ -112,10 +115,24 @@ module CTioga2 | |
| 112 115 |  | 
| 113 116 | 
             
                      # Now, we rearrange the lines...
         | 
| 114 117 | 
             
                      idx = -1
         | 
| 118 | 
            +
                      ruby = false
         | 
| 115 119 | 
             
                      for l in parsed_lines
         | 
| 116 120 | 
             
                        idx += 1
         | 
| 117 121 | 
             
                        interpreter.context.parsing_file(nil, io, lines_indices[idx])
         | 
| 118 | 
            -
                        if l =~ /^\s* | 
| 122 | 
            +
                        if l =~ /^\s*ruby\s*$/
         | 
| 123 | 
            +
                          ruby = ""
         | 
| 124 | 
            +
                        elsif ruby
         | 
| 125 | 
            +
                          if l =~ /^\s*ruby\s+end\s*$/
         | 
| 126 | 
            +
                            begin
         | 
| 127 | 
            +
                              Ruby.run_code(ruby)
         | 
| 128 | 
            +
                              ruby = false
         | 
| 129 | 
            +
                            rescue Exception => e
         | 
| 130 | 
            +
                              fatal { "Error #{e.inspect} running inline Ruby code at #{interpreter.context}" }
         | 
| 131 | 
            +
                            end
         | 
| 132 | 
            +
                          else
         | 
| 133 | 
            +
                            ruby << l
         | 
| 134 | 
            +
                          end
         | 
| 135 | 
            +
                        elsif l =~ /^\s*([a-zA-Z0-9_-]+)\s*(\??)(=|:=)\s*(.*)/
         | 
| 119 136 | 
             
                          symbol = $1
         | 
| 120 137 | 
             
                          value = InterpreterString.parse_until_unquoted(StringIO.new($4),"\n", false)
         | 
| 121 138 | 
             
                          override = !($2 == '?')
         |