Files
uutils.github.io/dev/src/uu_paste/paste.rs.html
T
2022-02-13 02:36:51 +00:00

324 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source of the Rust file `src&#x2F;uu&#x2F;paste&#x2F;src&#x2F;paste.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>paste.rs - source</title><link rel="stylesheet" type="text/css" href="../../normalize.css"><link rel="stylesheet" type="text/css" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><link rel="stylesheet" type="text/css" href="../../dark.css" disabled ><link rel="stylesheet" type="text/css" href="../../ayu.css" disabled ><script id="default-settings" ></script><script src="../../storage.js"></script><script src="../../crates.js"></script><script defer src="../../main.js"></script><script defer src="../../source-script.js"></script><script defer src="../../source-files.js"></script>
<noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="alternate icon" type="image/png" href="../../favicon-16x16.png"><link rel="alternate icon" type="image/png" href="../../favicon-32x32.png"><link rel="icon" type="image/svg+xml" href="../../favicon.svg"><style type="text/css">#crate-search{background-image:url("../../down-arrow.svg");}</style></head><body class="rustdoc source"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="sidebar-menu" role="button">&#9776;</div><a href='../../uu_paste/index.html'><div class='logo-container rust-logo'><img src='../../rust-logo.png' alt='logo'></div></a></nav><div class="theme-picker"><button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"><img width="18" height="18" alt="Pick another theme!" src="../../brush.svg"></button><div id="theme-choices" role="menu"></div></div><nav class="sub"><form class="search-form"><div class="search-container"><div><select id="crate-search"><option value="All crates">All crates</option></select><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"></div><button type="button" id="help-button" title="help">?</button><a id="settings-menu" href="../../settings.html" title="settings"><img width="18" height="18" alt="Change settings" src="../../wheel.svg"></a></div></form></nav><section id="main" class="content"><div class="example-wrap"><pre class="line-numbers"><span id="1"> 1</span>
<span id="2"> 2</span>
<span id="3"> 3</span>
<span id="4"> 4</span>
<span id="5"> 5</span>
<span id="6"> 6</span>
<span id="7"> 7</span>
<span id="8"> 8</span>
<span id="9"> 9</span>
<span id="10"> 10</span>
<span id="11"> 11</span>
<span id="12"> 12</span>
<span id="13"> 13</span>
<span id="14"> 14</span>
<span id="15"> 15</span>
<span id="16"> 16</span>
<span id="17"> 17</span>
<span id="18"> 18</span>
<span id="19"> 19</span>
<span id="20"> 20</span>
<span id="21"> 21</span>
<span id="22"> 22</span>
<span id="23"> 23</span>
<span id="24"> 24</span>
<span id="25"> 25</span>
<span id="26"> 26</span>
<span id="27"> 27</span>
<span id="28"> 28</span>
<span id="29"> 29</span>
<span id="30"> 30</span>
<span id="31"> 31</span>
<span id="32"> 32</span>
<span id="33"> 33</span>
<span id="34"> 34</span>
<span id="35"> 35</span>
<span id="36"> 36</span>
<span id="37"> 37</span>
<span id="38"> 38</span>
<span id="39"> 39</span>
<span id="40"> 40</span>
<span id="41"> 41</span>
<span id="42"> 42</span>
<span id="43"> 43</span>
<span id="44"> 44</span>
<span id="45"> 45</span>
<span id="46"> 46</span>
<span id="47"> 47</span>
<span id="48"> 48</span>
<span id="49"> 49</span>
<span id="50"> 50</span>
<span id="51"> 51</span>
<span id="52"> 52</span>
<span id="53"> 53</span>
<span id="54"> 54</span>
<span id="55"> 55</span>
<span id="56"> 56</span>
<span id="57"> 57</span>
<span id="58"> 58</span>
<span id="59"> 59</span>
<span id="60"> 60</span>
<span id="61"> 61</span>
<span id="62"> 62</span>
<span id="63"> 63</span>
<span id="64"> 64</span>
<span id="65"> 65</span>
<span id="66"> 66</span>
<span id="67"> 67</span>
<span id="68"> 68</span>
<span id="69"> 69</span>
<span id="70"> 70</span>
<span id="71"> 71</span>
<span id="72"> 72</span>
<span id="73"> 73</span>
<span id="74"> 74</span>
<span id="75"> 75</span>
<span id="76"> 76</span>
<span id="77"> 77</span>
<span id="78"> 78</span>
<span id="79"> 79</span>
<span id="80"> 80</span>
<span id="81"> 81</span>
<span id="82"> 82</span>
<span id="83"> 83</span>
<span id="84"> 84</span>
<span id="85"> 85</span>
<span id="86"> 86</span>
<span id="87"> 87</span>
<span id="88"> 88</span>
<span id="89"> 89</span>
<span id="90"> 90</span>
<span id="91"> 91</span>
<span id="92"> 92</span>
<span id="93"> 93</span>
<span id="94"> 94</span>
<span id="95"> 95</span>
<span id="96"> 96</span>
<span id="97"> 97</span>
<span id="98"> 98</span>
<span id="99"> 99</span>
<span id="100">100</span>
<span id="101">101</span>
<span id="102">102</span>
<span id="103">103</span>
<span id="104">104</span>
<span id="105">105</span>
<span id="106">106</span>
<span id="107">107</span>
<span id="108">108</span>
<span id="109">109</span>
<span id="110">110</span>
<span id="111">111</span>
<span id="112">112</span>
<span id="113">113</span>
<span id="114">114</span>
<span id="115">115</span>
<span id="116">116</span>
<span id="117">117</span>
<span id="118">118</span>
<span id="119">119</span>
<span id="120">120</span>
<span id="121">121</span>
<span id="122">122</span>
<span id="123">123</span>
<span id="124">124</span>
<span id="125">125</span>
<span id="126">126</span>
<span id="127">127</span>
<span id="128">128</span>
<span id="129">129</span>
<span id="130">130</span>
<span id="131">131</span>
<span id="132">132</span>
<span id="133">133</span>
<span id="134">134</span>
<span id="135">135</span>
<span id="136">136</span>
<span id="137">137</span>
<span id="138">138</span>
<span id="139">139</span>
<span id="140">140</span>
<span id="141">141</span>
<span id="142">142</span>
<span id="143">143</span>
<span id="144">144</span>
<span id="145">145</span>
<span id="146">146</span>
<span id="147">147</span>
<span id="148">148</span>
<span id="149">149</span>
<span id="150">150</span>
<span id="151">151</span>
<span id="152">152</span>
<span id="153">153</span>
<span id="154">154</span>
<span id="155">155</span>
<span id="156">156</span>
<span id="157">157</span>
<span id="158">158</span>
<span id="159">159</span>
<span id="160">160</span>
</pre><pre class="rust"><code><span class="comment">// * This file is part of the uutils coreutils package.</span>
<span class="comment">// *</span>
<span class="comment">// * (c) Alex Lyon &lt;arcterus@mail.com&gt;</span>
<span class="comment">// *</span>
<span class="comment">// * For the full copyright and license information, please view the LICENSE</span>
<span class="comment">// * file that was distributed with this source code.</span>
<span class="comment">// spell-checker:ignore (ToDO) delim</span>
<span class="kw">use</span> <span class="ident">clap</span>::{<span class="ident">crate_version</span>, <span class="ident">App</span>, <span class="ident">AppSettings</span>, <span class="ident">Arg</span>};
<span class="kw">use</span> <span class="ident">std::fs::File</span>;
<span class="kw">use</span> <span class="ident">std::io</span>::{<span class="ident">stdin</span>, <span class="ident">stdout</span>, <span class="ident">BufRead</span>, <span class="ident">BufReader</span>, <span class="ident">Read</span>, <span class="ident">Write</span>};
<span class="kw">use</span> <span class="ident">std::path::Path</span>;
<span class="kw">use</span> <span class="ident">uucore::error</span>::{<span class="ident">FromIo</span>, <span class="ident">UResult</span>};
<span class="kw">static</span> <span class="ident">ABOUT</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;Write lines consisting of the sequentially corresponding lines from each
FILE, separated by TABs, to standard output.&quot;</span>;
<span class="kw">mod</span> <span class="ident">options</span> {
<span class="kw">pub</span> <span class="kw">const</span> <span class="ident">DELIMITER</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;delimiters&quot;</span>;
<span class="kw">pub</span> <span class="kw">const</span> <span class="ident">SERIAL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;serial&quot;</span>;
<span class="kw">pub</span> <span class="kw">const</span> <span class="ident">FILE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;file&quot;</span>;
}
<span class="comment">// Wraps BufReader and stdin</span>
<span class="kw">fn</span> <span class="ident">read_line</span><span class="op">&lt;</span><span class="ident">R</span>: <span class="ident">Read</span><span class="op">&gt;</span>(
<span class="ident">reader</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="kw-2">&amp;mut</span> <span class="ident">BufReader</span><span class="op">&lt;</span><span class="ident">R</span><span class="op">&gt;</span><span class="op">&gt;</span>,
<span class="ident">buf</span>: <span class="kw-2">&amp;mut</span> <span class="ident">String</span>,
) -&gt; <span class="ident">std::io::Result</span><span class="op">&lt;</span><span class="ident">usize</span><span class="op">&gt;</span> {
<span class="kw">match</span> <span class="ident">reader</span> {
<span class="prelude-val">Some</span>(<span class="ident">reader</span>) =&gt; <span class="ident">reader</span>.<span class="ident">read_line</span>(<span class="ident">buf</span>),
<span class="prelude-val">None</span> =&gt; <span class="ident">stdin</span>().<span class="ident">read_line</span>(<span class="ident">buf</span>),
}
}
<span class="attribute">#[<span class="ident">uucore::main</span>]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">uumain</span>(<span class="ident">args</span>: <span class="kw">impl</span> <span class="ident">uucore::Args</span>) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">matches</span> <span class="op">=</span> <span class="ident">uu_app</span>().<span class="ident">get_matches_from</span>(<span class="ident">args</span>);
<span class="kw">let</span> <span class="ident">serial</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">is_present</span>(<span class="ident">options::SERIAL</span>);
<span class="kw">let</span> <span class="ident">delimiters</span> <span class="op">=</span> <span class="ident">matches</span>.<span class="ident">value_of</span>(<span class="ident">options::DELIMITER</span>).<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">files</span> <span class="op">=</span> <span class="ident">matches</span>
.<span class="ident">values_of</span>(<span class="ident">options::FILE</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">map</span>(<span class="op">|</span><span class="ident">s</span><span class="op">|</span> <span class="ident">s</span>.<span class="ident">to_owned</span>())
.<span class="ident">collect</span>();
<span class="ident">paste</span>(<span class="ident">files</span>, <span class="ident">serial</span>, <span class="ident">delimiters</span>)
}
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">uu_app</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>() -&gt; <span class="ident">App</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="ident">App::new</span>(<span class="ident">uucore::util_name</span>())
.<span class="ident">version</span>(<span class="macro">crate_version!</span>())
.<span class="ident">about</span>(<span class="ident">ABOUT</span>)
.<span class="ident">setting</span>(<span class="ident">AppSettings::InferLongArgs</span>)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">options::SERIAL</span>)
.<span class="ident">long</span>(<span class="ident">options::SERIAL</span>)
.<span class="ident">short</span>(<span class="string">&#39;s&#39;</span>)
.<span class="ident">help</span>(<span class="string">&quot;paste one file at a time instead of in parallel&quot;</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">options::DELIMITER</span>)
.<span class="ident">long</span>(<span class="ident">options::DELIMITER</span>)
.<span class="ident">short</span>(<span class="string">&#39;d&#39;</span>)
.<span class="ident">help</span>(<span class="string">&quot;reuse characters from LIST instead of TABs&quot;</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;LIST&quot;</span>)
.<span class="ident">default_value</span>(<span class="string">&quot;\t&quot;</span>)
.<span class="ident">hide_default_value</span>(<span class="bool-val">true</span>),
)
.<span class="ident">arg</span>(
<span class="ident">Arg::new</span>(<span class="ident">options::FILE</span>)
.<span class="ident">value_name</span>(<span class="string">&quot;FILE&quot;</span>)
.<span class="ident">multiple_occurrences</span>(<span class="bool-val">true</span>)
.<span class="ident">default_value</span>(<span class="string">&quot;-&quot;</span>),
)
}
<span class="kw">fn</span> <span class="ident">paste</span>(<span class="ident">filenames</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>, <span class="ident">serial</span>: <span class="ident">bool</span>, <span class="ident">delimiters</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">UResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">files</span> <span class="op">=</span> <span class="ident">Vec::with_capacity</span>(<span class="ident">filenames</span>.<span class="ident">len</span>());
<span class="kw">for</span> <span class="ident">name</span> <span class="kw">in</span> <span class="ident">filenames</span> {
<span class="kw">let</span> <span class="ident">file</span> <span class="op">=</span> <span class="kw">if</span> <span class="ident">name</span> <span class="op">==</span> <span class="string">&quot;-&quot;</span> {
<span class="prelude-val">None</span>
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="ident">path</span> <span class="op">=</span> <span class="ident">Path::new</span>(<span class="kw-2">&amp;</span><span class="ident">name</span>);
<span class="kw">let</span> <span class="ident">r</span> <span class="op">=</span> <span class="ident">File::open</span>(<span class="ident">path</span>).<span class="ident">map_err_context</span>(<span class="ident">String::new</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Some</span>(<span class="ident">BufReader::new</span>(<span class="ident">r</span>))
};
<span class="ident">files</span>.<span class="ident">push</span>(<span class="ident">file</span>);
}
<span class="kw">let</span> <span class="ident">delimiters</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">char</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">unescape</span>(<span class="ident">delimiters</span>).<span class="ident">chars</span>().<span class="ident">collect</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">delim_count</span> <span class="op">=</span> <span class="number">0</span>;
<span class="kw">let</span> <span class="ident">stdout</span> <span class="op">=</span> <span class="ident">stdout</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">stdout</span> <span class="op">=</span> <span class="ident">stdout</span>.<span class="ident">lock</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">output</span> <span class="op">=</span> <span class="ident">String::new</span>();
<span class="kw">if</span> <span class="ident">serial</span> {
<span class="kw">for</span> <span class="ident">file</span> <span class="kw">in</span> <span class="kw-2">&amp;mut</span> <span class="ident">files</span> {
<span class="ident">output</span>.<span class="ident">clear</span>();
<span class="kw">loop</span> {
<span class="kw">match</span> <span class="ident">read_line</span>(<span class="ident">file</span>.<span class="ident">as_mut</span>(), <span class="kw-2">&amp;mut</span> <span class="ident">output</span>) {
<span class="prelude-val">Ok</span>(<span class="number">0</span>) =&gt; <span class="kw">break</span>,
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; {
<span class="kw">if</span> <span class="ident">output</span>.<span class="ident">ends_with</span>(<span class="string">&#39;\n&#39;</span>) {
<span class="ident">output</span>.<span class="ident">pop</span>();
}
<span class="ident">output</span>.<span class="ident">push</span>(<span class="ident">delimiters</span>[<span class="ident">delim_count</span> <span class="op">%</span> <span class="ident">delimiters</span>.<span class="ident">len</span>()]);
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">map_err_context</span>(<span class="ident">String::new</span>)),
}
<span class="ident">delim_count</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
}
<span class="ident">output</span>.<span class="ident">pop</span>();
<span class="macro">writeln!</span>(<span class="ident">stdout</span>, <span class="string">&quot;{}&quot;</span>, <span class="ident">output</span>)<span class="question-mark">?</span>;
}
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">eof</span> <span class="op">=</span> <span class="macro">vec!</span>[<span class="bool-val">false</span>; <span class="ident">files</span>.<span class="ident">len</span>()];
<span class="kw">loop</span> {
<span class="ident">output</span>.<span class="ident">clear</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">eof_count</span> <span class="op">=</span> <span class="number">0</span>;
<span class="kw">for</span> (<span class="ident">i</span>, <span class="ident">file</span>) <span class="kw">in</span> <span class="ident">files</span>.<span class="ident">iter_mut</span>().<span class="ident">enumerate</span>() {
<span class="kw">if</span> <span class="ident">eof</span>[<span class="ident">i</span>] {
<span class="ident">eof_count</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
} <span class="kw">else</span> {
<span class="kw">match</span> <span class="ident">read_line</span>(<span class="ident">file</span>.<span class="ident">as_mut</span>(), <span class="kw-2">&amp;mut</span> <span class="ident">output</span>) {
<span class="prelude-val">Ok</span>(<span class="number">0</span>) =&gt; {
<span class="ident">eof</span>[<span class="ident">i</span>] <span class="op">=</span> <span class="bool-val">true</span>;
<span class="ident">eof_count</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
}
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; {
<span class="kw">if</span> <span class="ident">output</span>.<span class="ident">ends_with</span>(<span class="string">&#39;\n&#39;</span>) {
<span class="ident">output</span>.<span class="ident">pop</span>();
}
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">map_err_context</span>(<span class="ident">String::new</span>)),
}
}
<span class="ident">output</span>.<span class="ident">push</span>(<span class="ident">delimiters</span>[<span class="ident">delim_count</span> <span class="op">%</span> <span class="ident">delimiters</span>.<span class="ident">len</span>()]);
<span class="ident">delim_count</span> <span class="op">+</span><span class="op">=</span> <span class="number">1</span>;
}
<span class="kw">if</span> <span class="ident">files</span>.<span class="ident">len</span>() <span class="op">==</span> <span class="ident">eof_count</span> {
<span class="kw">break</span>;
}
<span class="comment">// Remove final delimiter</span>
<span class="ident">output</span>.<span class="ident">pop</span>();
<span class="macro">writeln!</span>(<span class="ident">stdout</span>, <span class="string">&quot;{}&quot;</span>, <span class="ident">output</span>)<span class="question-mark">?</span>;
<span class="ident">delim_count</span> <span class="op">=</span> <span class="number">0</span>;
}
}
<span class="prelude-val">Ok</span>(())
}
<span class="comment">// Unescape all special characters</span>
<span class="comment">// TODO: this will need work to conform to GNU implementation</span>
<span class="kw">fn</span> <span class="ident">unescape</span>(<span class="ident">s</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">String</span> {
<span class="ident">s</span>.<span class="ident">replace</span>(<span class="string">&quot;\\n&quot;</span>, <span class="string">&quot;\n&quot;</span>)
.<span class="ident">replace</span>(<span class="string">&quot;\\t&quot;</span>, <span class="string">&quot;\t&quot;</span>)
.<span class="ident">replace</span>(<span class="string">&quot;\\\\&quot;</span>, <span class="string">&quot;\\&quot;</span>)
.<span class="ident">replace</span>(<span class="string">&#39;\\&#39;</span>, <span class="string">&quot;&quot;</span>)
}
</code></pre></div>
</section><section id="search" class="content hidden"></section><div id="rustdoc-vars" data-root-path="../../" data-current-crate="uu_paste" data-search-index-js="../../search-index.js" data-search-js="../../search.js"></div>
</body></html>