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.
- data/Manifest.txt +3 -0
- data/README.txt +3 -81
- data/bin/bibdown +2 -520
- data/bin/mandown-sample +124 -0
- data/lib/bibdown_lib.rb +537 -0
- data/lib/mandown/version.rb +1 -1
- data/test/test_bibdown.rb +94 -0
- data/website/index.html +92 -32
- data/website/index.txt +72 -22
- data/website/template.rhtml +1 -1
- metadata +7 -2
data/bin/mandown-sample
ADDED
@@ -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)
|
data/lib/bibdown_lib.rb
ADDED
@@ -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
|