Version 0.2.0: RDB_ICASE, Changelog, --version, angepasste Man-Pages

This commit is contained in:
wkh
2026-10-11 21:24:11 +02:00
parent b5b28798ac
commit 8f6dc852ff
18 changed files with 259 additions and 4 deletions
+16
View File
@@ -7,6 +7,7 @@ require 'open3'
require 'date'
require 'tmpdir'
require 'fileutils'
require_relative 'rdb/version'
module Rdb
ROOT = File.expand_path('..', __dir__)
@@ -16,6 +17,21 @@ module Rdb
COMMANDS = {}
class << self
# RDB_ICASE=1 makes column names match without regard to case. An exact
# match always wins; several case-insensitive matches are an error.
def icase?
!%w[0 no false].include?(ENV['RDB_ICASE'].to_s.downcase) && !ENV['RDB_ICASE'].to_s.empty?
end
def column_index(head, name)
exact = head.index(name)
return exact if exact || !icase?
hits = head.each_index.select { |i| head[i].casecmp?(name) }
die "column name '#{name}' is ambiguous: #{hits.map { |i| head[i] }.join(', ')}" if hits.size > 1
hits.first
end
def die(msg)
abort "#{File.basename($PROGRAM_NAME)}: #{msg}"
end
+3 -2
View File
@@ -15,8 +15,9 @@ Rdb.register('column', 'Display columns of a table in any order', 'column [ Colu
t = table_in
next t.write if args.empty?
idx = args.map { |a| t.head.index(a) }
t.with(head: args, rows: t.rows.map { |r| idx.map { |i| i ? r[i] : '' } }).write
idx = args.map { |a| Rdb.column_index(t.head, a) }
head = args.each_with_index.map { |a, n| idx[n] ? t.head[idx[n]] : a }
t.with(head: head, rows: t.rows.map { |r| idx.map { |i| i ? r[i] : '' } }).write
end
Rdb.alias_for('project', 'column')
+19
View File
@@ -40,6 +40,24 @@ module Rdb
# Replace column names in an awk expression with $N, leaving strings,
# regexes and other identifiers alone.
AWK_WORDS = %w[BEGIN END NR NF FS OFS ORS RS FNR FILENAME SUBSEP RSTART RLENGTH ENVIRON ARGC ARGV
if else while for do in break continue next exit return function delete getline
print printf length substr index split sub gsub match sprintf sin cos atan2 exp log
sqrt int rand srand tolower toupper system].freeze
# With RDB_ICASE, a word that is not an awk keyword or function call may
# name a column in any case, provided that exactly one column fits.
def icase_column(names, expr, i)
return unless Rdb.icase?
word = expr[i..][/\A\w+/].to_s
return if word.empty? || AWK_WORDS.include?(word) || expr[i + word.size..].to_s.match?(/\A\s*\(/)
hits = names.select { |n, _| n.casecmp?(word) }
Rdb.die "column name '#{word}' is ambiguous: #{hits.map(&:first).join(', ')}" if hits.size > 1
hits.first
end
def to_awk(expr, head)
names = head.each_with_index.sort_by { |n, _| -n.size }
out = +''
@@ -59,6 +77,7 @@ module Rdb
i = j + 1
elsif c.match?(/[A-Za-z_#]/) && (i.zero? || !expr[i - 1].match?(/[\w$]/))
hit = names.find { |n, _| !n.empty? && expr[i, n.size] == n && !expr[i + n.size].to_s.match?(/\w/) }
hit ||= icase_column(names, expr, i)
if hit
out << "$#{hit[1] + 1}"
i += hit[0].size
+1 -1
View File
@@ -53,7 +53,7 @@ module Rdb
end
def column(name)
@head.index(name) || Rdb.die("#{path}: no column named '#{name}'")
Rdb.column_index(@head, name) || Rdb.die("#{path}: no column named '#{name}'")
end
def row_at(offset)
+1 -1
View File
@@ -60,7 +60,7 @@ module Rdb
end
def index_of(name)
@head.index(name) || Rdb.die("no column named '#{name}'")
Rdb.column_index(@head, name) || Rdb.die("no column named '#{name}'")
end
def to_s
+5
View File
@@ -0,0 +1,5 @@
# frozen_string_literal: true
module Rdb
VERSION = '0.2.0'
end