mandown 0.0.7 → 0.0.8

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,124 @@
1
+ # Please note that the copyright of the manuscript is owned by The PLoS
2
+ # Medicine Editors and their work is licensed according to the Creative
3
+ # Commons Attribution License.
4
+
5
+ def sample
6
+ <<END
7
+ Lethal Injection Is Not Humane
8
+ ==============================
9
+
10
+ The PLoS Medicine Editors
11
+
12
+ Citation: The PLoS Medicine Editors (2007) Lethal Injection Is Not Humane. PLoS Med 4(4): e171 doi:10.1371/journal.pmed.0040171
13
+
14
+ Published: April 24, 2007
15
+
16
+ Copyright: © 2007 The PLoS Medicine Editors. This is an open-access article distributed under the terms of the Creative Commons Attribution License, which permits unrestricted use, distribution, and reproduction in any medium, provided the original author and source are credited.
17
+
18
+ E-mail: medicine_editors@plos.org
19
+
20
+ This month's issue of PLoS Medicine contains a research article on three protocols used in lethal injection, the current method of execution for most US states. Despite the British Royal Commission on Capital Punishment advising against lethal injection half a century ago cite:Emanuel, the United Nations General Assembly affirming the desirability of abolishing the death penalty in 1971, and the European Union explicitly banning the death penalty in all circumstances cite:EU, execution—predominantly by lethal injection—is still practiced in many countries. During 2005 at least 2,148 people were executed in 22 countries in cases recorded by Amnesty International; the actual numbers were certainly higher. The majority of these executions took place in China, where fleets of mobile execution vans have been deployed to facilitate prompt, low-profile executions by lethal injection. Iran, Saudi Arabia, and the US together with China accounted for 94% of executions in 2005 cite:AmInt.
21
+
22
+ Following its introduction to the US in 1982, lethal injection became the primary method of execution there, largely replacing execution by hanging, firing squad, gas chamber, and electrocution. Each of these older methods has come to be seen as inhumane or excessively violent by most states, but each remains an option in a handful of others. Of the 53 executions in the US in 2006, all but one (an electrocution) were carried out using lethal injection cite:DPIC.
23
+
24
+ In recent months, concerns over botched lethal injections have put the method on hold in a dozen or so of the 36 US states that have the death penalty. Following a particularly agonizing execution in December 2006, the US District Court ruled that California's lethal injection protocol was unconstitutional. The governors of Florida and Tennessee suspended executions pending review of their states' lethal injection protocols. A court ruling in December 2006 suspended Maryland's executions, and New Jersey is considering an outright ban on its death penalty following a 2004 court order requiring the state to justify its lethal injection process. Executions are on hold in several other states pending legal proceedings cite:DPIC.
25
+
26
+ In this context, the editors of PLoS Medicine believe it is timely to publish a research article reporting shortcomings of lethal injection protocols. Strictly speaking, this article has little to do with medicine. Execution by lethal injection, even if it uses tools of intensive care such as intravenous tubing and beeping heart monitors, has the same relationship to medicine that an executioner's axe has to surgery. Nonetheless, there is a need for greater openness in public discussion and consideration of the death penalty, including its unpalatable details.
27
+
28
+ Challenges to the constitutionality of lethal injection have thus far been based largely on accounts of suffering resulting from unskilled administration. The American Medical Association, the American Nurses Association, the Society of Correctional Physicians, and a number of state medical boards have banned as unethical any causative role for medical professionals in executions cite:Gawande. Accordingly, in lethal injection procedures intravenous access has often been attempted (with frequent failures) by untrained staff, the execution mixture has precipitated and blocked IV tubes, and lethal doses have been unreliably calculated cite:Koniaris. Anesthesia has failed, chemical burns have occurred, and suffering has proceeded for 30 minutes or longer. Although this suffering might be seen as a consequence of professional refusal to participate in executions, this refusal also appears to be one of the primary forces motivating reexamination of lethal injection by the courts.
29
+
30
+ The current article by Koniaris and colleagues gives further cause for concern by questioning whether, even if “perfectly” administered, the protocols would achieve their stated aim of causing death without inflicting inhumane punishment. The authors analyzed several cases from three states: California, North Carolina, and Virginia. (Texas, the state with the largest number of lethal injections, does not release data from executions.) These lethal injection protocols use the barbiturate thiopental (intended to sedate and to suppress breathing), the neuromuscular blocker pancuronium (which paralyzes, causing respiratory arrest but also preventing agonal movements that might indicate suffering), and the electrolyte potassium (intended to cause cardiac arrest). Such protocols are intended to provide redundancy, such that each drug is given at a dose that would by itself cause death. However, in analyzing data from actual executions, Koniaris and colleagues report that thiopental and potassium do not consistently result in death. In fact, individuals undergoing execution have continued to breathe after the injection of thiopental, and their hearts have continued to beat following injection of potassium; in these cases, the authors conclude, it is quite likely that those being executed have experienced asphyxiation while conscious and unable to move, and possibly an intense burning pain throughout the body from the potassium injection.
31
+
32
+ Each of the editors of PLoS Medicine opposes the death penalty. It is not our intention to encourage further research to “improve” lethal injection protocols. As editors of a medical journal, we must ensure that research is ethical, and there is no ethical way to establish the humaneness of procedures for killing people who do not wish to die. Human research to further the ends of governments at the expense of individual lives is an obvious violation of the Declaration of Helsinki, which was conceived largely in response to the atrocities of Nazi “medicine” in order to articulate an international standard for ethical human experimentation cite:WMA. Whatever local law might say in a given place and time, no ethical researcher would propose a study to establish such procedures, no ethical reviewers would approve it, and no ethical journal would publish it. The acceptability of lethal injection under the US Constitution's Eighth Amendment ban on inhumane punishment has never been established; the data presented by Koniaris and colleagues adds to the evidence that lethal injection is simply the latest in a long line of execution methods that have been found to be inhumane. It is time for the US to join the majority of countries worldwide in recognizing that there is no humane way of forcibly killing someone.
33
+
34
+ Apart from the issue of whether humane execution can exist, we must also consider the accuracy of convictions resulting in death sentences. Execution of wrongfully sentenced individuals is obviously unacceptable, yet between 1973 and 2004 in the US, 118 prisoners who had been sentenced to death were later released on grounds of innocence cite:AmInt2. Of 197 convictions in the US that were subsequently exonerated by DNA evidence, 14 were at one time sentenced to death or served time on death row cite:InProj. Racial bias in sentencing likely accounts for much of this error; more than half of the exonerees were African Americans, and the rate of death sentences in the US among those convicted of killing a white victim is considerably higher than for murderers of blacks. Given this potential for fatal error, how can any objective person support the death penalty, which allows for no correction?
35
+
36
+ We support the recent decision of Craig Watkins, the new district attorney of Dallas, Texas, to examine hundreds of cases over the past 30 years to see whether DNA tests might reveal wrongful convictions cite:McGonigle. Such errors are inevitable when an implicit goal of sentencing, and particularly of imposing the death penalty, is not rational but emotional: the desire for revenge. As one law professor stated in a recent New York Times Magazine article on lethal injection, “Retribution, the conscious affliction of pain and suffering because and only because some people deserve it, is the essence of punishment” cite:Weil. But if the personal satisfaction of seeing criminals “get what they deserve” really reflects the intentions of Americans, why has the US seen a transition away from firing squads, hanging, or even drawing and quartering? Why was capital punishment illegal for a decade until it was reinstated by a Supreme Court ruling in 1976? Why have some US states rejected the death penalty completely, and others suspended its use? Why has the US followed the course associated with totalitarian states and rejected by other democracies in this matter?
37
+
38
+ Clearly, the death penalty is a matter of profound ambivalence in American society. Courts and state governments are saying that if capital punishment exists, it must not be cruel or visibly violent. Physicians and nurses are saying that their involvement in executions is below any acceptable conception of professional ethics. How to reconcile the needs of a society given to vengeance but outwardly abhorrent of cruelty or violence, trusting of medical science's trappings but indifferent to their use in killing, expecting the highest ethics of its physicians but willing to medicalize the execution chamber? The new data in PLoS Medicine will further strengthen the constitutional case for the abandonment of execution in the US. As a moral society, the US should take a leading role in the abandonment of executions worldwide.
39
+
40
+ # Bibliography
41
+
42
+ Emanuel:
43
+ authors: Emanuel, L L & Bienen, L B
44
+ title: Physician participation in executions (editorial)
45
+ journal: Ann Intern Med
46
+ volume: 135
47
+ pages: 922--924
48
+ year: 2001
49
+
50
+ EU:
51
+ organization: European Union
52
+ title: The EU's human rights & democratisation policy
53
+ url: http://ec.europa.eu/comm/external_relations/human_rights/adp/index.htm
54
+ accessed: 19 March 2007
55
+
56
+ AmInt:
57
+ organization: Amnesty International
58
+ title: Facts and statistics on the death penalty
59
+ url: http://web.amnesty.org/pages/deathpenalty-statistics-eng
60
+ accessed: 19 March 2007
61
+ year: 2007
62
+
63
+ DPIC:
64
+ organization: Death Penalty Information Center
65
+ title: Seaerchable database of executions
66
+ url: http://www.deathpenaltyinfo.org/executions.php
67
+ accessed: 19 March 2007
68
+ year: 2007
69
+
70
+ Gawande:
71
+ authors: Gawande, A
72
+ title: When law and ethics collide---Why physicians participate in executions
73
+ journal: New Engl J Med
74
+ volume: 354
75
+ pages: 1221--1229
76
+ year: 2006
77
+
78
+ Koniaris:
79
+ authors: Koniaris, L G & Zimmers, T A & Lubarsky, D A & Sheldon, J P
80
+ title: Inadequate anaesthesia in lethal injection for execution
81
+ journal: Lancet
82
+ volume: 365
83
+ pages: 1412--1414
84
+ year: 2005
85
+
86
+ WMA:
87
+ organization: World Medical Association
88
+ title: Policy Statement
89
+ url: http://www.wma.net/e/policy/b3.htm
90
+ accessed: 19 March 2007
91
+ year: 2007
92
+
93
+ AmInt2:
94
+ organization: Amnesty International
95
+ title: 'The death penalty worldwide: Developments in 2004'
96
+ url: http://web.amnesty.org/library/Index/ENGACT500012005
97
+ accessed: 19 March 2007
98
+ year: 2005
99
+
100
+ InProj:
101
+ organization: The Innocence Project
102
+ title: Facts on post-conviction DNA exonerations
103
+ url: http://www.innocenceproject.org/Content/351.php
104
+ accessed: 19 March 2007
105
+
106
+ McGonigle:
107
+ authors: McGonigle, S
108
+ title: Innocence Project to review Dallas County convictions
109
+ journal: The Dallas Morning News
110
+ url: http://www.dallasnews.com/sharedcontent/dws/dn/latestnews/stories/021607dnmetinnocence.179e9f3.html
111
+ accessed: 19 March 2007
112
+ year: 2007
113
+
114
+ Weil:
115
+ authors: Weil, E
116
+ title: The needle and the damage done
117
+ journal: New York Times (Magazine)
118
+ url: http://www.nytimes.com/2007/02/11/magazine/11injection.t.html?ex=1328850000&en=98538f95b199b74e&ei=5088&partner=rssnyt&emc=rss
119
+ accessed: 19 March 2007
120
+ year: 2007
121
+ END
122
+ end
123
+
124
+ STDOUT.puts(sample)
@@ -0,0 +1,537 @@
1
+ #################### License ###################################################
2
+ #
3
+ # Copyright (c) 2008 Chris Rose
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ #
18
+ ################################################################################
19
+
20
+ require 'yaml'
21
+
22
+ # Define the text that is displayed when the user asks for documentation
23
+ def documentation
24
+ <<END
25
+
26
+
27
+ bibdown --- part of the Mandown set of tools.
28
+
29
+ bibdown processes standard input, builds a bibliography from a YAML-format set
30
+ of references and inserts citation keys.
31
+
32
+ Copyright © 2008 Chris Rose.
33
+ Distributed according to the GNU General Public License.
34
+
35
+ Usage:
36
+ ------
37
+ cat infile.txt | bibdown > outfile.txt
38
+
39
+ Syntax:
40
+ -------
41
+
42
+ Place references at the end of your Markdown file in a level 1 section
43
+ called 'Bibliography' using the exact string '# Bibliography' (as given in the
44
+ example below). Cite references in your text using 'cite:MyKey', where 'MyKey'
45
+ is a key to one of your references. Keys may contain any characters, but end
46
+ with a space character (i.e. 'cite:SomeKey' refers to the key 'SomeKey', while
47
+ 'cite:Some Key' refers to the key 'Some').
48
+
49
+ ------------------------------- Example -------------------------------------
50
+ ...
51
+ This is some text that needs to cite the very important work of Jones and
52
+ Smith cite:Jones.
53
+ ...
54
+
55
+ # Bibliogrqaphy
56
+
57
+ Jones:
58
+ authors: Jones, Bob & Smith, Fred J.
59
+ title: Spaghetti-Wall Interactions
60
+ journal: Am. J. Pasta Phys.
61
+ volume: 3
62
+ number: 2
63
+ month: January
64
+ year: 2008
65
+ pages: 111--112
66
+ note: In press.
67
+ ------------------------------- End of example ------------------------------
68
+
69
+ Suppoted fields:
70
+ ----------------
71
+
72
+ The following fields are supported by bibdown and all are optional; you may
73
+ use other arbitrarily-named fields, but they will be ignored (by this version
74
+ of bibdown, at least).
75
+
76
+ authors -- Use 'surname, first names' format; separate authors with '&'.
77
+ e.g. "Einstein, Albert & Bohr, Neils"
78
+ organization -- Use if the publication is authored by an organization.
79
+ e.g. "Amnesty International"
80
+ title -- The title of the reference.
81
+ e.g. "Some Clever Stuff on Quantum Physics"
82
+ journal -- The name of the journal; this field causes the reference to be
83
+ treated as an article in a journal.
84
+ e.g. "Int. J. Quan. Phys."
85
+ conference -- The name of the conference; this field causes the reference to
86
+ be treated as a paper in a conference proceedings.
87
+ e.g. "Medical Image Understanding and Analysis"
88
+ booktitle -- The title of a book; this field causes the reference to be
89
+ treated as a book.
90
+ e.g. "Moby Dick"
91
+ chapter -- The chapter in a book being cited; only valid for references
92
+ that use the booktitle field.
93
+ e.g. "4"
94
+ edition -- The edition of a book being cited; only valid for references
95
+ that use the booktitle field.
96
+ e.g. "5"
97
+ editors -- The editors of a book being cited; only valid for references
98
+ that use the booktitle field.
99
+ e.g. "Harris, Thomas & Hopper, Dennis"
100
+ isbn -- The ISBN number of a book being cited; only valid for references
101
+ that use the booktitle field.
102
+ e.g. "9783540356257"
103
+ month -- The month of publication.
104
+ e.g. "January"
105
+ volume -- The volume of the publication being cited.
106
+ e.g. "2"
107
+ number -- The number/issue of the journal article being cited; only valid for
108
+ references that use the journal field.
109
+ e.g. "2"
110
+ pages -- The pages in the publication being referred to.
111
+ e.g. "201--211"
112
+ series -- The series the book being cited belongs to; only valid for
113
+ references that use the booktitle field.
114
+ e.g. "Mathematical Statistics"
115
+ url -- A URL for the publication being cited.
116
+ e.g. "http://www.something.com/somedocument"
117
+ accessed -- The date the URL was accessed (note: do not use this field without
118
+ also including a URL).
119
+ e.g. "28 January 2008"
120
+ year -- The year the publication being cited was published.
121
+ e.g. 2008
122
+ note -- Any notable comment about the publication being cited.
123
+ e.g. "In press."
124
+
125
+
126
+ Notes:
127
+ ------
128
+
129
+ You must use soft tabs (emulated using spaces) in the bibliography. If you
130
+ need to include a colon in the reference (e.g. in the title field), you
131
+ will need to surround the field entry in quotes (e.g. "title: 'Gnocci: nasty
132
+ or nice?'").
133
+
134
+ If you are going to process the resulting file (outfile.txt, in the usage
135
+ example given above), you may wish to use a double-dash for page ranges
136
+ (and be sure to use the 'smart typography' mode of Pandoc)---see the example
137
+ above.
138
+
139
+ See also:
140
+ ---------
141
+
142
+ Markdown -- http://daringfireball.net/projects/markdown/
143
+ Pandoc -- http://johnmacfarlane.net/pandoc/
144
+
145
+ END
146
+ end
147
+
148
+
149
+ # Given a symbol identifying a part of a citation (e.g. :journal), return the
150
+ # separator string that should follow it (e.g. a '. ' follows the name of the
151
+ # journal). (Note: include any following space!)
152
+ def get_sep(part)
153
+ sep = case part
154
+ when :authors, :organization, :title, :booktitle, :isbn, :series, :accessed, :year
155
+ '. '
156
+ when :journal, :conference, :chapter, :edition, :pages, :url
157
+ ', '
158
+ when :editors
159
+ ', editors. '
160
+ when :month, :note
161
+ ' '
162
+ when :number, :volume
163
+ ''
164
+ end
165
+
166
+ sep
167
+ end
168
+
169
+ # Define a function that takes a string and returns that string marked as being of :normal (upright) or :italic using Markdown notation.
170
+ def markdown_format(string, style)
171
+ case style
172
+ when :normal: string
173
+ when :italic: '*' + string + '*'
174
+ end
175
+ end
176
+
177
+ # Define a function to render a string as normal using Markdown notation.
178
+ def r_norm(string)
179
+ markdown_format(string, :normal)
180
+ end
181
+
182
+ # Define a function to render a string as italic using Markdown notation.
183
+ def r_ital(string)
184
+ markdown_format(string, :italic)
185
+ end
186
+
187
+
188
+ # Given a bib entry (a hash that maps the parts of a reference to the content
189
+ # for that reference), construct a string that can be used in a paper as the
190
+ # bibliographic entry for that entry. Also return information that can be used
191
+ # to sort the bibliography (first author surname, publication year). Also
192
+ # return the key that was used in the text to refer to this citation. Return a
193
+ # hash with fields :reference (containing the reference), :sort_info and :key.
194
+ # :sort_info is a hash with fields :surname and :year.
195
+ #
196
+ # See the documentation string above for details on what fields are supported
197
+ # and how they should behave.
198
+ def make_bib_entry_string(bib_entry, key)
199
+ # We'll encode the order in which the parts of the reference appear for the
200
+ # three types of reference in three arrays; we'll associate these arrays
201
+ # with symbols that specify the reference type.
202
+ order = {
203
+ :journal =>
204
+ [:authors, :organization, :title, :journal, :volume, :number, :pages,
205
+ :month, :year, :url, :accessed, :note],
206
+ :conference =>
207
+ [:authors, :organization, :title, :conference, :editors, :volume, :pages,
208
+ :month, :year, :isbn, :url, :accessed, :note],
209
+ :book =>
210
+ [:authors, :organization, :editors, :booktitle, :series, :edition,
211
+ :volume, :chapter, :pages, :month, :year, :isbn, :url, :accessed,
212
+ :note]}
213
+
214
+ # Cope with the misc type.
215
+ order[:misc] = order[:journal]
216
+
217
+ # Use an associative array to specify how each part of a citation should be
218
+ # styled. We map from the parts to functions which perform the required
219
+ # styling.
220
+ styles = {:authors => proc {|x| r_norm(x)},
221
+ :organization => proc {|x| r_norm(x)}, :title => proc {|x| r_norm(x)},
222
+ :journal => proc {|x| r_ital(x)}, :conference => proc {|x| r_ital(x)},
223
+ :booktitle => proc {|x| r_ital(x)}, :chapter => proc {|x| r_norm(x)},
224
+ :edition => proc {|x| r_norm(x)}, :editors => proc {|x| r_norm(x)},
225
+ :isbn => proc {|x| r_norm(x)}, :month => proc {|x| r_norm(x)},
226
+ :note => proc {|x| r_norm(x)}, :number => proc {|x| r_norm(x)},
227
+ :pages => proc {|x| r_norm(x)}, :series => proc {|x| r_norm(x)},
228
+ :url => proc {|x| r_norm(x)}, :accessed => proc {|x| r_norm(x)},
229
+ :volume => proc {|x| r_norm(x)}, :year => proc {|x| r_norm(x)}}
230
+
231
+ # Make a copy for later, as we alter the original bib_entry object.
232
+ org_bib_entry = bib_entry.clone
233
+
234
+ # Make the author string and replace the entry in the bib_entry with the
235
+ # formatted version. Do similarly with the editors.
236
+ bib_entry['authors'] =
237
+ make_author_string(bib_entry['authors']) if !bib_entry['authors'].nil?
238
+ bib_entry['editors'] =
239
+ make_author_string(bib_entry['editors']) if !bib_entry['editors'].nil?
240
+
241
+ # See if we're making a journal article, conference paper or book reference.
242
+ ref_type = :journal unless bib_entry['journal'].nil?
243
+ ref_type = :conference unless bib_entry['conference'].nil?
244
+ ref_type = :book unless bib_entry['booktitle'].nil?
245
+ if !(defined? ref_type) || ref_type.nil?
246
+ ref_type = :misc
247
+ STDERR.puts('Note: Reference type not found for reference ' + key)
248
+ end
249
+
250
+ # Get the order for the type of entry we're dealing with.
251
+ order = order[ref_type]
252
+
253
+ # Iterate over the parts of the citation for this type of reference and
254
+ # build the bibliography entry.
255
+ bib_entry_string = ''
256
+ order.each do |part_name|
257
+ # Construct the part of the entry for the given part_name, taking into
258
+ # account the fact that some parts need to be formatted in certain ways.
259
+ if bib_entry[part_name.to_s] # If there is an entry for this part name...
260
+ part = bib_entry[part_name.to_s].to_s
261
+ else
262
+ part = ''
263
+ end
264
+
265
+ # Format the part of the reference using the appropriate style.
266
+ part = styles[part_name].call(part)
267
+
268
+ part = case part_name
269
+ when :authors, :organization, :booktitle, :isbn, :series, :year
270
+ part + '. '
271
+ when :title
272
+ # Only add an '.' if doesn't already end with a punctuation character.
273
+ if /[[:punct:]]$/.match(part): part + ' '
274
+ else part + '. '
275
+ end
276
+ when :conference
277
+ 'In proc. ' + part + ', '
278
+ when :journal, :conference, :chapter, :edition
279
+ part + ', '
280
+ when :editors
281
+ part + ', editors. '
282
+ when :month
283
+ part + ' '
284
+ when :volume
285
+ part
286
+ when :number, :note
287
+ '(' + part + ')'
288
+ when :pages
289
+ if ref_type == :journal
290
+ ':' + part + ', '
291
+ elsif ref_type == :conference || ref_type == :book
292
+ 'pp' + part + ', '
293
+ end
294
+ when :url
295
+ 'Available at: ' + part
296
+ when :accessed
297
+ ', accessed ' + part + '. '
298
+ else
299
+ part
300
+ end
301
+
302
+ bib_entry_string += part if bib_entry[part_name.to_s]
303
+ end
304
+
305
+ # Make sure the bib_entry_string ends with a punctuation character,
306
+ # appending a full stop if it doesn't.
307
+ bib_entry_string.strip!
308
+ bib_entry_string += '.' unless /[[:punct:]]$/.match(bib_entry_string)
309
+
310
+ # Get the surname for sorting purposes. Use the author as first preference
311
+ # if it is available, otherwise use the organisation, otherwise use a sort
312
+ # surname that will place it last.
313
+ sort_surname = 'ZZZ' # The default if we can't find something better.
314
+ sort_surname =
315
+ org_bib_entry[:organization] if !bib_entry['organization'].nil?
316
+ sort_surname =
317
+ get_first_author_surname(org_bib_entry) if !bib_entry['author'].nil?
318
+
319
+
320
+ # Make the hash to return.
321
+ { :reference => bib_entry_string,
322
+ :key => key,
323
+ :sort_info => {:surname => sort_surname, :year => bib_entry['year']}}
324
+ end
325
+
326
+ # Return the surname of the first author in lowercase.
327
+ def get_first_author_surname(bib_entry)
328
+ make_author_string(
329
+ bib_entry['authors'], true, true).split[0][0..-2].downcase
330
+ end
331
+
332
+
333
+ # Given a string of the form 'Chris James' turn it into a string of the form 'C. J.'
334
+ def make_initials(firstnames)
335
+ firstnames = firstnames.split(' ')
336
+ firstnames.each_index do |i|
337
+ firstnames[i] = firstnames[i][0].chr + '.'
338
+ end
339
+ end
340
+
341
+ # Given a string of the form 'Rose, Chris & Jones, Bob', make an authors
342
+ # string that can be placed in the bibliography.
343
+ #
344
+ # use_initials specifies whether the full firstnames are used, or whether
345
+ # initials are used instead.
346
+ #
347
+ # surname_first specifies whether the author surnames should appear before
348
+ # their first names or initials.
349
+ def make_author_string(authors, use_initials=true, surname_first=false)
350
+ # Strip out the individual authors and remove leading and trailing
351
+ # whitespace, and split each into surname and firstnames.
352
+ authors = authors.split('&')
353
+ authors.each_index do |i|
354
+ authors[i].strip!
355
+ authors[i] = authors[i].split(',')
356
+ authors[i][0].strip!
357
+ authors[i][1].strip!
358
+ end
359
+
360
+ # If we have to use first initials for the first names, then make them.
361
+ if use_initials
362
+ authors.each_index do |i|
363
+ authors[i][1] = make_initials(authors[i][1])
364
+ end
365
+ end
366
+
367
+ # Now make the authors string.
368
+ authors_string = ''
369
+ authors.each_index do |i|
370
+ # Get a string for the forename(s) for the i-th author.
371
+ this_forenames = ''
372
+ authors[i][1].each do |name_or_initial|
373
+ this_forenames += name_or_initial + ' '
374
+ end
375
+
376
+ # Concatenate the forename(s) and surname in the appropriate order.
377
+ if surname_first
378
+ authors_string += authors[i][0] + ', '
379
+ authors_string += this_forenames.rstrip
380
+ else
381
+ authors_string += this_forenames
382
+ authors_string += authors[i][0]
383
+ end
384
+ authors_string += ', ' unless i == authors.length-1 or i == authors.length-2
385
+ authors_string += ' and ' if i == authors.length-2
386
+ end
387
+
388
+ authors_string.strip! # Remove leading and trailing whitespace.
389
+ authors_string # Return the authors string.
390
+ end
391
+
392
+
393
+ # Given an array of bib_entries, each made using the make_bib_entry_string
394
+ # function, sort this array according to first author surname, or year of
395
+ # publication, or by the order in which the papers were cited in the text.
396
+ #
397
+ # keys_in_order must be an array containing the keys used in the text, in the
398
+ # order the keys appear in the text, without repetition. by must be one of
399
+ # :surname, :year or :order_in_text
400
+ def sort_bib_entries(bib_entries, keys_in_order, by = :surname)
401
+ case by
402
+ when :surname, :year
403
+ bib_entries.sort {|x,y| x[:sort_info][by] <=> y[:sort_info][by]}
404
+ when :order_in_text
405
+ to_return = []
406
+ keys_in_order.each do |key|
407
+ bib_entries.each do |entry|
408
+ to_return.push(entry) if entry[:key] == key
409
+ end
410
+ end
411
+ to_return
412
+ end
413
+ end
414
+
415
+
416
+ # Given a string containing the YAML for the bibliography, and an array
417
+ # containing the keys in the order they appear in the text (without
418
+ # repetitions), make an array of strings where each string is a bibliographic
419
+ # entry (i.e. can be placed directly in the bibliography). The entries
420
+ # returned will be sorted in an appropriate order.
421
+ def make_bib_entries(bibliography_yaml, keys_in_order)
422
+ # Convert the YAML text to a Ruby data type.
423
+ objs = YAML.load(bibliography_yaml)
424
+
425
+ # Make each bibliography entry string (the references).
426
+ bib_entries = Array.new
427
+ objs.each_key do |key|
428
+ bib_entries.push(make_bib_entry_string(objs[key], key))
429
+ end
430
+
431
+ # Sort the references & return.
432
+ sort_bib_entries(bib_entries, keys_in_order, :order_in_text)
433
+ end
434
+
435
+ # Define a function that returns true if bib_entries contains an entry for a
436
+ # given citation key.
437
+ def has_key?(key, bib_entries)
438
+ ret_val = false
439
+ bib_entries.each do |entry|
440
+ ret_val = true if entry[:key] == key
441
+ end
442
+ ret_val
443
+ end
444
+
445
+ # Get an array that contains the reference keys in the order they are cited,
446
+ # without repetitions.
447
+ def get_keys_in_order(plaintext)
448
+ all_keys = plaintext.scan(/cite:\w*/)
449
+ all_keys.uniq! # Remove duplicates.
450
+ uniq_keys = []
451
+ all_keys.each {|x| uniq_keys.push(x.split('cite:')[1])} # Remove the 'cite:'
452
+ uniq_keys
453
+ end
454
+
455
+ # Convert bib_entries into a string that can be placed at the end of the
456
+ # plaintext as the bibliography. The parenthesis style using the
457
+ # citation_parens argument.
458
+ def render_bibliography(bib_entries, citation_parens)
459
+ ret_val = "\n"
460
+ bib_entries.each_index do |i|
461
+ ret_val += # The reference number.
462
+ citation_parens[0].chr + (i+1).to_s + citation_parens[1].chr
463
+ ret_val += ' ' + bib_entries[i][:reference] # The reference.
464
+ ret_val += " \n" # __\n is Markdown for a linebreak.
465
+ end
466
+
467
+ ret_val
468
+ end
469
+
470
+ # Given the plaintext containing the key-based citations, and the bib_entries,
471
+ # make the final manuscript by replacing the key-based citations (in the text)
472
+ # with human-readable citations and place the bibliography at the end. Specify
473
+ # the parenthesis style using the optional citation_parens argument.
474
+ def make_manuscript(plaintext, bib_entries, citation_parens='[]')
475
+ bib_entries.each_index do |i|
476
+ plaintext.gsub!("cite:#{bib_entries[i][:key]}",
477
+ citation_parens[0].chr + "#{i+1}" + citation_parens[1].chr)
478
+ end
479
+
480
+ plaintext + render_bibliography(bib_entries, citation_parens)
481
+ end
482
+
483
+ # Check the final manuscript for instances of cite:SomeKey (for example), and
484
+ # return an array of messages identifying the keys that were not defined in
485
+ # the bibliography.
486
+ def check_missing_citations(manuscript)
487
+ ret_val = []
488
+ # Get the remaining keys.
489
+ remaining_keys = get_keys_in_order(manuscript)
490
+ remaining_keys.each do |key|
491
+ ret_val.push('The following reference key was undefined: ' + key)
492
+ end
493
+
494
+ ret_val
495
+ end
496
+
497
+ # Read the text containing the citations from standard input, process the
498
+ # references and send the result to standard output, reporting errors to
499
+ # standard error. This program is written to allow it to be chained with other
500
+ # manuscript-processing tools in a UNIX pipeline. To read/write from/to files,
501
+ # do:
502
+ #
503
+ # cat my-paper.txt | ruby make_paper.rb > my-paper-with-bib.txt
504
+ def bibdown_main
505
+ # Handle request for documentation.
506
+ if ARGV.length > 0 && ARGV[0] == '--help'
507
+ puts documentation
508
+ exit
509
+ end
510
+
511
+ # Read the .txt file from standard input and get the plain text and the
512
+ # bibliography
513
+ parts = STDIN.readlines('# Bibliography')
514
+ plaintext = parts[0]
515
+ bibliography_yaml = parts[1]
516
+
517
+ # Get an array that contains the reference keys in the order they are cited,
518
+ # without repetitions.
519
+ keys_in_order = get_keys_in_order(plaintext)
520
+
521
+ # Make a list of bibliography enties, sorted in the correct order.
522
+ bib_entries = make_bib_entries(bibliography_yaml, keys_in_order)
523
+
524
+ # Now make the final manuscript by replacing the key-based citations (in the
525
+ # text) with human-readable citations and place the bibliography at the end.
526
+ manuscript = make_manuscript(plaintext, bib_entries)
527
+
528
+ # Send the manuscript to standard output.
529
+ STDOUT.puts(manuscript)
530
+
531
+ # Now perform some checks for possible user errors and report then on
532
+ # standard error.
533
+ user_errors = []
534
+ user_errors.concat(check_missing_citations(manuscript))
535
+ user_errors.each {|x| STDERR.puts(x)} # Report the user errors.
536
+
537
+ end
@@ -2,7 +2,7 @@ module Mandown #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 7
5
+ TINY = 8
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end