Last active
January 3, 2016 19:59
-
-
Save cdlm/8512372 to your computer and use it in GitHub Desktop.
Script to help translators of http://thecodelesscode.com
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'cgi' | |
input = ARGV.empty? ? $stdin : StringIO(ARGV.join(' ')) | |
input.each_line do |line| | |
puts CGI::escape(line.chomp) | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# for n in `./find-links | ./cgi-escape`; do | |
# touch "the-codeless-code/fr-cdlm/$n.txt" | |
# done | |
DIR="${1:-the-codeless-code/$CODELESS_TRANSLATION}" | |
ack --no-filename --output='$1' '\[\[([^]|]+)(\||\]\])' "$DIR" | sort | uniq |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# | |
# Checks staged contents of changed files for normal spaces left where french | |
# typography rules would require a non-breaking space: | |
# - inside guillemots « and » | |
# - before double punctuation signs :;!? | |
exit if ENV['CODELESS_TRANSLATION'].nil? | |
begin | |
require 'paint' | |
Paint::SHORTCUTS[:highlight] = { | |
file: Paint.color(:blue), | |
warn: Paint.color(nil, :red) | |
} | |
include Paint::Highlight | |
rescue LoadError | |
def no_paint(s) s end | |
alias file no_paint | |
alias warn no_paint | |
end | |
FILE_GLOB = "the-codeless-code/#{ENV['CODELESS_TRANSLATION']}/case-*.txt" | |
HEADER_PATTERN = /^([[:alnum:]]|\.)+: / | |
NON_NBSP = /[^\u00A0]/ # anything but a | |
ENTITY = /(?<entity>&[^\s;]+;)/ | |
BAD_AFTER = /(?<=«)#{NON_NBSP}/ | |
BAD_BEFORE = /#{NON_NBSP}(?=[:;?!»])/ | |
PATTERN = Regexp.union ENTITY, BAD_BEFORE, BAD_AFTER | |
def files_to_check | |
IO.popen(%w(git diff --cached --name-only --diff-filter=ACM)) do |io| | |
io.each_line.map(&:chomp).select { |each| File.fnmatch? FILE_GLOB, each } | |
end | |
end | |
def staged_contents filename, &block | |
IO.popen(['git', 'show', ":#{filename}"]) do |io| | |
io.each_line.with_index &block | |
end | |
end | |
problems_in_total = 0 | |
files_to_check.each do |name| | |
in_header = true | |
first_in_file = true | |
staged_contents(name) do |line,num| | |
line.chomp! | |
next if in_header && HEADER_PATTERN === line | |
in_header = false | |
problems_on_line = 0 | |
line = line.gsub PATTERN do | |
match = Regexp.last_match | |
if match[:entity].nil? | |
problems_on_line += 1 | |
warn(match) | |
else | |
match | |
end | |
end | |
unless problems_on_line.zero? | |
puts file(name) if first_in_file | |
puts " #{num + 1}: #{line}" | |
problems_in_total += problems_on_line | |
first_in_file = false | |
end | |
end | |
end | |
if problems_in_total > 0 | |
puts "\n#{problems_in_total} occurrences of bad or missing spaces near punctuation" | |
exit 42 | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'cri' # gem install cri | |
require 'fileutils' | |
def translation_dir translation | |
d = File.join(ROOT, translation) | |
raise "No such translation #{translation}" unless File.directory? d | |
d | |
end | |
def case_file case_num, translation | |
File.join(translation_dir(translation), "case-#{case_num}.txt") | |
end | |
def available? case_num, translation | |
File.exist?(case_file(case_num, translation)) | |
end | |
def case_numbers translation | |
cases = Dir.glob(File.join(translation_dir(translation), 'case-[0-9]*.txt')) | |
cases.map { |each| /(\d+)\.txt/.match(each)[1].to_i }.sort | |
end | |
def untranslated_cases src, dest | |
case_numbers(src) - case_numbers(dest) | |
end | |
def root_command | |
Cri::Command.define do | |
name NAME | |
usage "#{NAME} [case] [src=#{DEFAULT_SOURCE}] [dest=#{DEFAULT_DESTINATION}]" | |
summary "copies a case before starting its translation" | |
description <<EOS | |
Copies selected case from an authoritative translation src to an in-progress translation dest. | |
Case can be specified either by explicit number, or selected among available cases by a keyword. | |
Available cases are those that have a translation in src but not in dest. | |
Recognized selection keywords are: | |
current (latest translated case), | |
next (first available case), | |
last (latest available case), | |
random. | |
Environment variables: you must set CODELESS_TRANSLATION to the name of the translation directory to copy cases to. If you work from another translation, setting CODELESS_SOURCE overrides the default (en-qi). | |
EOS | |
flag :h, :help, "show command usage" do |_, cmd| | |
puts cmd.help | |
exit | |
end | |
flag nil, :dryrun, "only say what would be done" | |
flag nil, :overwrite, "copy even if destination case exists" | |
flag :e, :edit, "open case in $EDITOR" | |
run do |opts, args, cmd| | |
selection = args[0] || DEFAULT_SELECTION | |
src = args[1] || DEFAULT_SOURCE | |
dest = args[2] || DEFAULT_DESTINATION | |
case_num = case selection | |
when /^\d+$/ then args[0].to_i | |
when /^c(ur(rent)?)?$/ then case_numbers(dest).last | |
when /^n(ext)?$/ then untranslated_cases(src, dest).first | |
when /^l(a(te)?st)?$/ then untranslated_cases(src, dest).last | |
when /^r(and(om)?)?$/ then untranslated_cases(src, dest).sample | |
else raise "Invalid case selector #{selection}" | |
end | |
raise "No available cases to translate from #{src} to #{dest}" if case_num.nil? | |
raise "No case ##{case_num} in translation #{src}" unless available?(case_num, src) | |
raise "Case ##{case_num} already exists in translation #{dest}" if available?(case_num, dest) && !(opts[:overwrite] || opts[:edit]) | |
unless available?(case_num, dest) && opts[:edit] | |
puts "Copying case ##{case_num} (#{src} -> #{dest})" | |
FileUtils.cp case_file(case_num, src), case_file(case_num, dest) unless opts[:dryrun] | |
end | |
if opts[:edit] | |
exec ENV['EDITOR'], case_file(case_num, dest) unless opts[:dryrun] | |
end | |
end | |
end | |
end | |
# ...and here we go | |
begin | |
NAME = File.basename(__FILE__) | |
ROOT = File.join(File.expand_path(File.dirname(__FILE__)), 'the-codeless-code') | |
DEFAULT_SELECTION = ENV['CODELESS_SELECTION'] || 'next' | |
DEFAULT_SOURCE = ENV['CODELESS_SOURCE'] || 'en-qi' | |
DEFAULT_DESTINATION = ENV['CODELESS_TRANSLATION'] || raise(StandardError, "No destination translation given, please set $CODELESS_TRANSLATION") | |
root_command.run(ARGV) | |
rescue StandardError => e | |
puts e.message | |
exit 1 | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment