diachronr 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9b2e2d058e7f5f172916afd00f908040629c680a
4
+ data.tar.gz: d2f09d22747c1a296eb934cb46cd71a2b532d000
5
+ SHA512:
6
+ metadata.gz: 3359a50b580a06e15ff588e7dffc85e7cf8ab7e2ef4714111e26881722cd6a3950f133eeb00dd648e30b4e5b9b650e3591117c0a16e6c4b17c6e56bf375bfdd5
7
+ data.tar.gz: 3db05f89d3c90c60014449877464124d5dd1696320ea57106ea89a81a142f171ba60b211e4333ed23fe000d2513674f07feb478f52b5808e75a2fc584ebbe033
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1 @@
1
+ 2.4.1
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bkmrk.gemspec
4
+ gemspec
5
+
@@ -0,0 +1,6 @@
1
+ Copyright (c) 2017 Miker Irick
2
+
3
+ "THE BEER-WARE LICENSE":
4
+ Miker Irick wrote this crap. As long as you retain this notice you
5
+ can do whatever you want with this stuff. If we meet some day, and you think
6
+ this stuff is worth it, you can buy me a beer in return.
@@ -0,0 +1,30 @@
1
+ # Intro
2
+
3
+ This is a basic gem for applying diachronic sound changes to words based on supplied rules. It is largely inspired by Mark Rosenfelder's Sound Change Applier(http://www.zompist.com/sca2.html, y'all should buy his books, too).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'diachronr'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install diachronr
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage documentation. For now, check out the tests
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Ensure your tests pass, coverage is at 100%, and rubocop reports clean
28
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
29
+ 5. Push to the branch (`git push origin my-new-feature`)
30
+ 6. Create new Pull Request
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ task :console do
4
+ require 'irb'
5
+ require 'irb/completion'
6
+ require 'diachronr' # You know what to do.
7
+ ARGV.clear
8
+ IRB.start
9
+ end
10
+
11
+ task :test do
12
+ Dir.glob('./test/*_test.rb').each { |file| require file }
13
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'diachronr/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'diachronr'
8
+ gem.version = Diachronr::VERSION
9
+ gem.authors = ['Miker Irick']
10
+ gem.email = ['michaelirick@gmail.com']
11
+ gem.description = 'applies sound changes to constructed languages'
12
+ gem.summary = 'applies diachronic sound changes to constructed languages'
13
+ gem.homepage = 'http://michaelirick.com'
14
+ gem.license = 'Nonstandard'
15
+
16
+ gem.files = `git ls-files`.split($RS)
17
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ['lib']
20
+
21
+ gem.add_dependency 'slop', '~> 3.4'
22
+
23
+ gem.add_development_dependency 'simplecov', '~> 0'
24
+ gem.add_development_dependency 'pry', '~> 0'
25
+ gem.add_development_dependency 'rake', '~> 0'
26
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'diachronr/version'
4
+ require 'diachronr/rewrite'
5
+ require 'diachronr/category'
6
+ require 'diachronr/rule'
7
+ require 'diachronr/ruleset'
8
+
9
+ # module for applying sound changes to constructed languages
10
+ module Diachronr
11
+ # Your code goes here...
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diachronr
4
+ # rules for groups of sounds
5
+ class Category
6
+ attr_accessor :sign, :contents
7
+
8
+ def initialize(category)
9
+ @sign, @contents = category.split '='
10
+ end # initialize
11
+ end # class
12
+ end # module
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diachronr
4
+ # rules for rewriting character variations and digraphs
5
+ class Rewrite
6
+ attr_accessor :from, :to
7
+
8
+ def initialize(rewrite)
9
+ @from, @to = rewrite.split '|'
10
+ end # initialize
11
+
12
+ def apply(target)
13
+ target.gsub @from, @to
14
+ end # apply
15
+
16
+ def reverse(target)
17
+ target.gsub @to, @from
18
+ end
19
+ end # class
20
+ end # module
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diachronr
4
+ # rule for applying a single sound change
5
+ class Rule
6
+ attr_accessor :from
7
+ attr_accessor :to
8
+ attr_accessor :condition
9
+
10
+ def initialize(rule)
11
+ @from, @to, @condition = rule.split '/'
12
+ end # initialize
13
+
14
+ def to_s
15
+ "'#{@from}' > '#{@to}' / '#{@condition}'"
16
+ end # to_s
17
+
18
+ def category?(categories)
19
+ categories?(from, categories) || categories?(condition, categories)
20
+ end
21
+
22
+ def categories?(value, categories)
23
+ !get_categories(value, categories).empty?
24
+ end
25
+
26
+ def get_categories(value, categories)
27
+ categories.select { |c| value.include? c.sign }
28
+ end
29
+
30
+ def new_to(categories, category_index, index)
31
+ t = get_categories(to, categories)[category_index]
32
+ return to if t.nil?
33
+ t.contents[index]
34
+ end # new_to
35
+
36
+ def new_from(category, char)
37
+ from.gsub category.sign, char
38
+ end
39
+
40
+ def category_rules(categories)
41
+ rules = []
42
+ get_categories(from, categories).each_with_index do |cat, i|
43
+ cat.contents.each_char.with_index do |f, fi|
44
+ rules << Rule.new(
45
+ "#{new_from(cat, f)}/#{new_to(categories, i, fi)}/#{condition}"
46
+ )
47
+ end
48
+ end
49
+ rules
50
+ end
51
+
52
+ def condition_rules(categories)
53
+ rules = []
54
+ get_categories(condition, categories).each do |cat|
55
+ cat.contents.each_char do |c|
56
+ new_condition = condition.gsub cat.sign, c
57
+ rules << Rule.new("#{from}/#{to}/#{new_condition}")
58
+ end
59
+ end
60
+ rules
61
+ end
62
+
63
+ def merge_matches(target, matches)
64
+ new_target = target.dup
65
+ matches.each do |match|
66
+ match.each_char.with_index do |m, i|
67
+ new_target[i] = m if target[i] != m
68
+ end
69
+ end
70
+ new_target
71
+ end
72
+
73
+ def apply_categories(target, categories)
74
+ # parse categories, apply each exploded rule to the original target
75
+ # merge the changes together
76
+ rules = category_rules(categories) + condition_rules(categories)
77
+ matches = rules.map { |r| r.apply target, categories: categories }
78
+ matches.uniq!
79
+ matches.delete target
80
+
81
+ matches.count == 1 ? matches.first : merge_matches(target, matches)
82
+ end
83
+
84
+ def apply(target, options = {})
85
+ categories = options[:categories] || []
86
+ return apply_categories target, categories if category? categories
87
+
88
+ # construct regex from condition
89
+ from_condition = @condition.gsub '_', @from
90
+ to_condition = @condition.gsub '_', @to
91
+
92
+ # change word boundaries to regex
93
+ from_condition = Regexp.new from_condition.gsub('#', '\b')
94
+ to_condition.delete! '#'
95
+
96
+ # split on from_condition and join with to_condition
97
+ # if you need a limit higher than 10.... nope
98
+ split_target = target.split from_condition, 10
99
+ split_target.join to_condition
100
+ end # apply
101
+ end # class
102
+ end # module
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module Diachronr
6
+ # a set of rules, categories, and rewrites applicable to words
7
+ class RuleSet
8
+ attr_accessor :rules, :categories, :rewrites, :options
9
+
10
+ def initialize(rules, categories, rewrites, options = {})
11
+ @rules = rules
12
+ @categories = categories
13
+ @rewrites = rewrites
14
+ @options = options
15
+ end # initialize
16
+
17
+ def self.load(filename)
18
+ options = YAML.load_file filename
19
+ rules = options['rules'].map { |a| Diachronr::Rule.new(a) }
20
+ categories = options['categories'].map { |a| Diachronr::Category.new(a) }
21
+ rewrites = options['rewrites'].map { |a| Diachronr::Rewrite.new(a) }
22
+ RuleSet.new rules, categories, rewrites, options
23
+ end
24
+
25
+ def apply(target)
26
+ @rewrites.each do |rewrite|
27
+ target = rewrite.apply target
28
+ end # each
29
+
30
+ @rules.each do |rule|
31
+ target = rule.apply target, categories: @categories
32
+ end # each
33
+
34
+ @rewrites.each do |rewrite|
35
+ target = rewrite.reverse target
36
+ end # each
37
+ target
38
+ end # apply
39
+ end # class
40
+ end # module
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diachronr
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'test_helper.rb'
2
+ require 'minitest/autorun'
3
+ require 'diachronr'
4
+
5
+ class DiachronrTest < Minitest::Test
6
+ def test_should_create_a_rule
7
+ r = Diachronr::Rule.new 'a//_'
8
+ assert_equal r.to_s, "'a' > '' / '_'"
9
+ end
10
+
11
+ def test_apply_simple_rule
12
+ r = Diachronr::Rule.new 'a//_'
13
+ assert_equal r.apply('taco'), 'tco'
14
+ end
15
+
16
+ def test_apply_condition
17
+ r = Diachronr::Rule.new 'a/b/d_e'
18
+ assert_equal r.apply('daetat'), 'dbetat'
19
+ end
20
+
21
+ def test_apply_word_boundry
22
+ r = Diachronr::Rule.new 'a/e/_#'
23
+ assert_equal r.apply('data'), 'date'
24
+ end
25
+
26
+ def test_apply_rewrite
27
+ r = Diachronr::Rewrite.new 'dh|ð'
28
+ assert_equal r.apply('edhel'), 'eðel'
29
+ end
30
+
31
+ def test_apply_ruleset
32
+ r = Diachronr::RuleSet.load 'test/fixtures/seonic_to_varag.yml'
33
+ r.options['seonic'].each do |seonic, varag|
34
+ assert_equal r.apply(seonic), varag
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,119 @@
1
+ rewrites:
2
+ - qu|q
3
+ - th|þ
4
+ - dh|ð
5
+ - sh|š
6
+ - ai|á
7
+ - au|à
8
+ - ei|é
9
+ - eu|è
10
+ - eo|è
11
+ - iu|ì
12
+ - ii|í
13
+ - oi|ò
14
+ - ou|ó
15
+ - ui|ù
16
+ - uu|ú
17
+ - h|c
18
+ categories:
19
+ - V=aiueo
20
+ - L=áàéèìíòóùú
21
+ - C=qwrtypsdfghjkzxcvbnmðþ
22
+ - A=tpkdbgvþsch
23
+ - B=þfctpkbdzgg
24
+ - D=tdðþ
25
+ - S=szš
26
+ - U=tpsfhkcþš
27
+ - F=ua
28
+ - G=ae
29
+ - N=âîûêô
30
+ rules:
31
+ - a/o/_
32
+ - u/a/_
33
+ - o/u/_
34
+ - i/e/_
35
+ - á/a/_
36
+ - à/a/_
37
+ - é/e/_
38
+ - è/e/_
39
+ - ì/i/_
40
+ - í/i/_
41
+ - ò/o/_
42
+ - ó/o/_
43
+ - ù/u/_
44
+ - ú/u/_
45
+ - k/h/#_
46
+ - t/þ/#_
47
+ - p/v/#_
48
+ - c//V_C
49
+ - sk/š/_
50
+ - A/B/_
51
+ - o/a/_
52
+ - ó/á/_
53
+ - m/n/_#
54
+ - m/n/_D
55
+ - L//_#
56
+ - en/in/_
57
+ - z//_#
58
+ - V//_#
59
+ - iu/ú/_#
60
+ - z/r/_
61
+ - q/ku/_
62
+ - e/o/_
63
+ - w/v/#_
64
+ - w//_i
65
+ - w//_e
66
+ - w/v/_a
67
+ - w/v/_o
68
+ - w/v/_u
69
+ - er/ir/_
70
+ - eD/iD/_
71
+ - hr/ks/_
72
+ - è/ú/_
73
+ - V//_#
74
+ - é/á/_
75
+ - F/G/_
76
+ - o/a/_
77
+ - r//_#
78
+ - i/e/U_
79
+ - oe/oi/_
80
+ - ao/au/_
81
+ - mn/nn/_
82
+ - i/e/_#
83
+ - aa/ai/_
84
+ seonic:
85
+ weson: varan
86
+ wesic: varag
87
+ shultus: shelth
88
+ tumun: demen
89
+ kousyo: gery
90
+ korwas: garw
91
+ menter: mintha
92
+ avtero: abtha
93
+ aneo: an # ana
94
+ alos: al
95
+ altas: alth
96
+ nemos: nam
97
+ saquos: rak
98
+ asas: a
99
+ alio: al # al
100
+ altero: altha
101
+ sever: raba
102
+ anvictos: anbath # anbagth
103
+ an: an
104
+ eisos: a
105
+ gonias: kan # kana
106
+ annos: ann
107
+ beras: pa
108
+ ber: pa
109
+ toquo: dak
110
+ anveldas: anbalt
111
+ coro: ga
112
+ octos: ath
113
+ abel: apal
114
+ meilus: mal # male
115
+ korius: ga # gare
116
+ kerric: garrag
117
+ anvo: anb
118
+ tactus: dath # dathe
119
+ luukas: lah
@@ -0,0 +1,2 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: diachronr
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Miker Irick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: slop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: simplecov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: applies sound changes to constructed languages
70
+ email:
71
+ - michaelirick@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".ruby-version"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - diachronr.gemspec
83
+ - lib/diachronr.rb
84
+ - lib/diachronr/category.rb
85
+ - lib/diachronr/rewrite.rb
86
+ - lib/diachronr/rule.rb
87
+ - lib/diachronr/ruleset.rb
88
+ - lib/diachronr/version.rb
89
+ - test/diachronr_test.rb
90
+ - test/fixtures/seonic_to_varag.yml
91
+ - test/test_helper.rb
92
+ homepage: http://michaelirick.com
93
+ licenses:
94
+ - Nonstandard
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.6.11
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: applies diachronic sound changes to constructed languages
116
+ test_files:
117
+ - test/diachronr_test.rb
118
+ - test/fixtures/seonic_to_varag.yml
119
+ - test/test_helper.rb