Skip to content

Instantly share code, notes, and snippets.

@mountainstorm
Last active August 29, 2015 13:57
Show Gist options
  • Save mountainstorm/9768081 to your computer and use it in GitHub Desktop.
Save mountainstorm/9768081 to your computer and use it in GitHub Desktop.
Simple highlight to allow dynamic highlighting of a search pattern
/*
* Copyright (c) 2014 Mountainstorm
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
(function ( $ ) {
function textNodesUnder(el){
var txt = '';
var rng = [];
var idx = 0;
var walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false);
var n;
while (n = walk.nextNode()) {
rng.push({start: idx, end: idx+n.length, node: n});
txt += n.nodeValue;
idx += n.length;
}
return {text: txt, ranges: rng};
}
function highlightMatches(el, pattern, highlightClass, casesensitive) {
var retval = [];
if (pattern != '') {
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
}
var rex = escapeRegExp(pattern);
// collate all the text node ranges
target = textNodesUnder(el);
// find all matches (case insensitive)
var matches = []
var regex = new RegExp(rex, casesensitive ? 'g': 'gi');
while (match = regex.exec(target.text)) {
matches.push(match.index);
}
// for each match find the segment it starts in
var m = 0;
var patternLength = pattern.length;
for (i in target.ranges) {
seg = target.ranges[i]
if (matches[m] >= seg.start && matches[m] < seg.end) {
// starts in this segment
var more = false;
var start = matches[m];
var end = start + patternLength;
if (end >= seg.end) {
// the rest of this segment is used up - but theres more ...
end = seg.end;
more = true;
}
// split this segments text node; adding a span around the matching text
nodeText = seg.node.nodeValue;
var before = document.createTextNode(nodeText.slice(0, start - seg.start));
var hlt = document.createTextNode(nodeText.slice(start - seg.start, end - seg.start));
var after = document.createTextNode(nodeText.slice(end - seg.start));
var span = document.createElement('span');
span.setAttribute('class', highlightClass);
span.appendChild(hlt);
seg.node.parentNode.insertBefore(before, seg.node);
seg.node.parentNode.insertBefore(span, seg.node);
seg.node.parentNode.insertBefore(after, seg.node);
// save our changes
var mod = {
parent: seg.node.parentNode,
before: before,
span: span,
after: after
}
retval.push(mod);
seg.node.parentNode.removeChild(seg.node);
// if theres more, look for remainer; else goto next match
if (more) {
matches[m] = end;
patternLength -= (seg.end - start);
} else {
m++; // next
patternLength = pattern.length;
if (m == matches.length) {
break; // done
}
}
}
} // for
}
return retval;
}
function unhighlightMatches(mods) {
for (var i = 0; i < mods.length; i++) {
var mod = mods[i];
// if span's first child is a text node - add in the contents of before
if ( mod.span.firstChild
&& mod.span.firstChild.nodeType == document.TEXT_NODE) {
mod.span.firstChild.nodeValue = mod.before.nodeValue + mod.span.firstChild.nodeValue;
}
// if span's last child is a text node - add in the contents of after
if ( mod.span.lastChild
&& mod.span.lastChild.nodeType == document.TEXT_NODE) {
mod.span.lastChild.nodeValue = mod.span.lastChild.nodeValue + mod.after.nodeValue;
}
// insert all of spans childNodes before 'before'
for (var j = 0; j < mod.span.childNodes.length; j++) {
mod.parent.insertBefore(mod.span.childNodes[j], mod.before);
}
// remove before, span and after
mod.parent.removeChild(mod.before);
mod.parent.removeChild(mod.span);
mod.parent.removeChild(mod.after);
}
}
$.fn.find_highlight = function(options) {
if (options.pattern == undefined) {
// un-highlight elements
return this.each(function() {
options.action(this);
var mods = $(this).data('mountainstorm.find.highlight')
if (mods != undefined) {
unhighlightMatches(mods);
}
});
} else {
// highlight with - options.pattern, options.class
return this.each(function() {
var mods = highlightMatches(this, options.pattern, options.class);
if ( options.pattern != ''
&& mods.length == 0
&& options.action) {
options.action(this);
}
$(this).data('mountainstorm.find.highlight', mods);
});
}
};
}( jQuery ));
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="jquery.find.highlight.js"></script>
<script>
function onChange() {
$('.hlcode').find_highlight();
$('.hlcode').find_highlight({
pattern: document.getElementById('pattern').value,
class: 'highlight'
})
}
</script>
<style>
.highlight { background: darkgray; }
</style>
<style>
pre .hll { background-color: #ffffcc }
pre { background: #f0f0f0; }
pre .c { color: #60a0b0; font-style: italic } /* Comment */
pre .err { border: 1px solid #FF0000 } /* Error */
pre .k { color: #007020; font-weight: bold } /* Keyword */
pre .o { color: #666666 } /* Operator */
pre .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
pre .cp { color: #007020 } /* Comment.Preproc */
pre .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
pre .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
pre .gd { color: #A00000 } /* Generic.Deleted */
pre .ge { font-style: italic } /* Generic.Emph */
pre .gr { color: #FF0000 } /* Generic.Error */
pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */
pre .gi { color: #00A000 } /* Generic.Inserted */
pre .go { color: #888888 } /* Generic.Output */
pre .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
pre .gs { font-weight: bold } /* Generic.Strong */
pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
pre .gt { color: #0044DD } /* Generic.Traceback */
pre .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
pre .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
pre .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
pre .kp { color: #007020 } /* Keyword.Pseudo */
pre .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
pre .kt { color: #902000 } /* Keyword.Type */
pre .m { color: #40a070 } /* Literal.Number */
pre .s { color: #4070a0 } /* Literal.String */
pre .na { color: #4070a0 } /* Name.Attribute */
pre .nb { color: #007020 } /* Name.Builtin */
pre .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
pre .no { color: #60add5 } /* Name.Constant */
pre .nd { color: #555555; font-weight: bold } /* Name.Decorator */
pre .ni { color: #d55537; font-weight: bold } /* Name.Entity */
pre .ne { color: #007020 } /* Name.Exception */
pre .nf { color: #06287e } /* Name.Function */
pre .nl { color: #002070; font-weight: bold } /* Name.Label */
pre .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
pre .nt { color: #062873; font-weight: bold } /* Name.Tag */
pre .nv { color: #bb60d5 } /* Name.Variable */
pre .ow { color: #007020; font-weight: bold } /* Operator.Word */
pre .w { color: #bbbbbb } /* Text.Whitespace */
pre .mf { color: #40a070 } /* Literal.Number.Float */
pre .mh { color: #40a070 } /* Literal.Number.Hex */
pre .mi { color: #40a070 } /* Literal.Number.Integer */
pre .mo { color: #40a070 } /* Literal.Number.Oct */
pre .sb { color: #4070a0 } /* Literal.String.Backtick */
pre .sc { color: #4070a0 } /* Literal.String.Char */
pre .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
pre .s2 { color: #4070a0 } /* Literal.String.Double */
pre .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
pre .sh { color: #4070a0 } /* Literal.String.Heredoc */
pre .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
pre .sx { color: #c65d09 } /* Literal.String.Other */
pre .sr { color: #235388 } /* Literal.String.Regex */
pre .s1 { color: #4070a0 } /* Literal.String.Single */
pre .ss { color: #517918 } /* Literal.String.Symbol */
pre .bp { color: #007020 } /* Name.Builtin.Pseudo */
pre .vc { color: #bb60d5 } /* Name.Variable.Class */
pre .vg { color: #bb60d5 } /* Name.Variable.Global */
pre .vi { color: #bb60d5 } /* Name.Variable.Instance */
pre .il { color: #40a070 } /* Literal.Number.Integer.Long */.syntax pre .hll { background-color: #49483e }
.syntax pre { background: #272822; color: #f8f8f2 }
.syntax pre .c { color: #75715e } /* Comment */
.syntax pre .err { color: #960050; background-color: #1e0010 } /* Error */
.syntax pre .k { color: #66d9ef } /* Keyword */
.syntax pre .l { color: #ae81ff } /* Literal */
.syntax pre .n { color: #f8f8f2 } /* Name */
.syntax pre .o { color: #f92672 } /* Operator */
.syntax pre .p { color: #f8f8f2 } /* Punctuation */
.syntax pre .cm { color: #75715e } /* Comment.Multiline */
.syntax pre .cp { color: #75715e } /* Comment.Preproc */
.syntax pre .c1 { color: #75715e } /* Comment.Single */
.syntax pre .cs { color: #75715e } /* Comment.Special */
.syntax pre .gd { color: #f92672 } /* Generic.Deleted */
.syntax pre .ge { font-style: italic } /* Generic.Emph */
.syntax pre .gi { color: #a6e22e } /* Generic.Inserted */
.syntax pre .gs { font-weight: bold } /* Generic.Strong */
.syntax pre .gu { color: #75715e } /* Generic.Subheading */
.syntax pre .kc { color: #66d9ef } /* Keyword.Constant */
.syntax pre .kd { color: #66d9ef } /* Keyword.Declaration */
.syntax pre .kn { color: #f92672 } /* Keyword.Namespace */
.syntax pre .kp { color: #66d9ef } /* Keyword.Pseudo */
.syntax pre .kr { color: #66d9ef } /* Keyword.Reserved */
.syntax pre .kt { color: #66d9ef } /* Keyword.Type */
.syntax pre .ld { color: #e6db74 } /* Literal.Date */
.syntax pre .m { color: #ae81ff } /* Literal.Number */
.syntax pre .s { color: #e6db74 } /* Literal.String */
.syntax pre .na { color: #a6e22e } /* Name.Attribute */
.syntax pre .nb { color: #f8f8f2 } /* Name.Builtin */
.syntax pre .nc { color: #a6e22e } /* Name.Class */
.syntax pre .no { color: #66d9ef } /* Name.Constant */
.syntax pre .nd { color: #a6e22e } /* Name.Decorator */
.syntax pre .ni { color: #f8f8f2 } /* Name.Entity */
.syntax pre .ne { color: #a6e22e } /* Name.Exception */
.syntax pre .nf { color: #a6e22e } /* Name.Function */
.syntax pre .nl { color: #f8f8f2 } /* Name.Label */
.syntax pre .nn { color: #f8f8f2 } /* Name.Namespace */
.syntax pre .nx { color: #a6e22e } /* Name.Other */
.syntax pre .py { color: #f8f8f2 } /* Name.Property */
.syntax pre .nt { color: #f92672 } /* Name.Tag */
.syntax pre .nv { color: #f8f8f2 } /* Name.Variable */
.syntax pre .ow { color: #f92672 } /* Operator.Word */
.syntax pre .w { color: #f8f8f2 } /* Text.Whitespace */
.syntax pre .mf { color: #ae81ff } /* Literal.Number.Float */
.syntax pre .mh { color: #ae81ff } /* Literal.Number.Hex */
.syntax pre .mi { color: #ae81ff } /* Literal.Number.Integer */
.syntax pre .mo { color: #ae81ff } /* Literal.Number.Oct */
.syntax pre .sb { color: #e6db74 } /* Literal.String.Backtick */
.syntax pre .sc { color: #e6db74 } /* Literal.String.Char */
.syntax pre .sd { color: #e6db74 } /* Literal.String.Doc */
.syntax pre .s2 { color: #e6db74 } /* Literal.String.Double */
.syntax pre .se { color: #ae81ff } /* Literal.String.Escape */
.syntax pre .sh { color: #e6db74 } /* Literal.String.Heredoc */
.syntax pre .si { color: #e6db74 } /* Literal.String.Interpol */
.syntax pre .sx { color: #e6db74 } /* Literal.String.Other */
.syntax pre .sr { color: #e6db74 } /* Literal.String.Regex */
.syntax pre .s1 { color: #e6db74 } /* Literal.String.Single */
.syntax pre .ss { color: #e6db74 } /* Literal.String.Symbol */
.syntax pre .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.syntax pre .vc { color: #f8f8f2 } /* Name.Variable.Class */
.syntax pre .vg { color: #f8f8f2 } /* Name.Variable.Global */
.syntax pre .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.syntax pre .il { color: #ae81ff } /* Literal.Number.Integer.Long */
</style>
</head>
<body onload="onReady()">
<input id="pattern" type="text" onkeyup="onChange()"/>
<div class="hlcode">
<div class="syntax"><pre><span class="kt">int</span>
<span class="nf">main</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
<span class="c1">// 记录需要被列出的目录</span>
<span class="k">struct</span> <span class="n">pending</span> <span class="o">*</span><span class="n">thispend</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">n_files</span><span class="p">;</span>
<span class="cm">/* The signals that are trapped, and the number of such signals. */</span>
<span class="k">static</span> <span class="kt">int</span> <span class="k">const</span> <span class="n">sig</span><span class="p">[]</span> <span class="o">=</span>
<span class="p">{</span>
<span class="cm">/* This one is handled specially. */</span>
<span class="n">SIGTSTP</span><span class="p">,</span>
<span class="cm">/* The usual suspects. */</span>
<span class="n">SIGALRM</span><span class="p">,</span> <span class="n">SIGHUP</span><span class="p">,</span> <span class="n">SIGINT</span><span class="p">,</span> <span class="n">SIGPIPE</span><span class="p">,</span> <span class="n">SIGQUIT</span><span class="p">,</span> <span class="n">SIGTERM</span><span class="p">,</span>
<span class="cp">#ifdef SIGPOLL</span>
<span class="n">SIGPOLL</span><span class="p">,</span>
<span class="cp">#endif</span>
<span class="cp">#ifdef SIGPROF</span>
<span class="n">SIGPROF</span><span class="p">,</span>
<span class="cp">#endif</span>
<span class="cp">#ifdef SIGVTALRM</span>
<span class="n">SIGVTALRM</span><span class="p">,</span>
<span class="cp">#endif</span>
<span class="cp">#ifdef SIGXCPU</span>
<span class="n">SIGXCPU</span><span class="p">,</span>
<span class="cp">#endif</span>
<span class="cp">#ifdef SIGXFSZ</span>
<span class="n">SIGXFSZ</span><span class="p">,</span>
<span class="cp">#endif</span>
<span class="p">};</span>
<span class="k">enum</span> <span class="p">{</span> <span class="n">nsigs</span> <span class="o">=</span> <span class="n">ARRAY_CARDINALITY</span> <span class="p">(</span><span class="n">sig</span><span class="p">)</span> <span class="p">};</span>
<span class="cp">#if ! SA_NOCLDSTOP</span>
<span class="kt">bool</span> <span class="n">caught_sig</span><span class="p">[</span><span class="n">nsigs</span><span class="p">];</span>
<span class="cp">#endif</span>
<span class="c1">// initialize_main 是为了 VMS 机器实现重定向和通配符</span>
<span class="c1">// 剩下来的都是些程序的初始化设置</span>
<span class="n">initialize_main</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">argc</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">argv</span><span class="p">);</span>
<span class="n">set_program_name</span> <span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="n">setlocale</span> <span class="p">(</span><span class="n">LC_ALL</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span>
<span class="n">bindtextdomain</span> <span class="p">(</span><span class="n">PACKAGE</span><span class="p">,</span> <span class="n">LOCALEDIR</span><span class="p">);</span>
<span class="n">textdomain</span> <span class="p">(</span><span class="n">PACKAGE</span><span class="p">);</span>
<span class="n">initialize_exit_failure</span> <span class="p">(</span><span class="n">LS_FAILURE</span><span class="p">);</span>
<span class="n">atexit</span> <span class="p">(</span><span class="n">close_stdout</span><span class="p">);</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">ARRAY_CARDINALITY</span> <span class="p">(</span><span class="n">color_indicator</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="o">==</span> <span class="n">ARRAY_CARDINALITY</span> <span class="p">(</span><span class="n">indicator_name</span><span class="p">));</span>
<span class="n">exit_status</span> <span class="o">=</span> <span class="n">EXIT_SUCCESS</span><span class="p">;</span>
<span class="n">print_dir_name</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">pending_dirs</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">current_time</span><span class="p">.</span><span class="n">tv_sec</span> <span class="o">=</span> <span class="n">TYPE_MINIMUM</span> <span class="p">(</span><span class="kt">time_t</span><span class="p">);</span>
<span class="n">current_time</span><span class="p">.</span><span class="n">tv_nsec</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="c1">// decode_switched 函数负责处理程序的参数, 并设置相关的选项</span>
<span class="c1">// 返回的值是 optind</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">decode_switches</span> <span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>
<span class="c1">// 从名字可以看出是和高亮显示相关的, 没细看</span>
<span class="k">if</span> <span class="p">(</span><span class="n">print_with_color</span><span class="p">)</span>
<span class="n">parse_ls_color</span> <span class="p">();</span>
<span class="cm">/* Test print_with_color again, because the call to parse_ls_color</span>
<span class="cm"> may have just reset it -- e.g., if LS_COLORS is invalid. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">print_with_color</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Avoid following symbolic links when possible. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">is_colored</span> <span class="p">(</span><span class="n">C_ORPHAN</span><span class="p">)</span>
<span class="o">||</span> <span class="p">(</span><span class="n">is_colored</span> <span class="p">(</span><span class="n">C_EXEC</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">color_symlink_as_referent</span><span class="p">)</span>
<span class="o">||</span> <span class="p">(</span><span class="n">is_colored</span> <span class="p">(</span><span class="n">C_MISSING</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">format</span> <span class="o">==</span> <span class="n">long_format</span><span class="p">))</span>
<span class="n">check_symlink_color</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="cm">/* If the standard output is a controlling terminal, watch out</span>
<span class="cm"> for signals, so that the colors can be restored to the</span>
<span class="cm"> default state if "ls" is suspended or interrupted. */</span>
<span class="k">if</span> <span class="p">(</span><span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">tcgetpgrp</span> <span class="p">(</span><span class="n">STDOUT_FILENO</span><span class="p">))</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">j</span><span class="p">;</span>
<span class="cp">#if SA_NOCLDSTOP</span>
<span class="k">struct</span> <span class="n">sigaction</span> <span class="n">act</span><span class="p">;</span>
<span class="n">sigemptyset</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">caught_signals</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nsigs</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sigaction</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">act</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">act</span><span class="p">.</span><span class="n">sa_handler</span> <span class="o">!=</span> <span class="n">SIG_IGN</span><span class="p">)</span>
<span class="n">sigaddset</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">caught_signals</span><span class="p">,</span> <span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="p">}</span>
<span class="n">act</span><span class="p">.</span><span class="n">sa_mask</span> <span class="o">=</span> <span class="n">caught_signals</span><span class="p">;</span>
<span class="n">act</span><span class="p">.</span><span class="n">sa_flags</span> <span class="o">=</span> <span class="n">SA_RESTART</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nsigs</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sigismember</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">caught_signals</span><span class="p">,</span> <span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">]))</span>
<span class="p">{</span>
<span class="n">act</span><span class="p">.</span><span class="n">sa_handler</span> <span class="o">=</span> <span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">SIGTSTP</span> <span class="o">?</span> <span class="n">stophandler</span> <span class="o">:</span> <span class="n">sighandler</span><span class="p">;</span>
<span class="n">sigaction</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="o">&amp;</span><span class="n">act</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#else</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nsigs</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">caught_sig</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">signal</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">SIG_IGN</span><span class="p">)</span> <span class="o">!=</span> <span class="n">SIG_IGN</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">caught_sig</span><span class="p">[</span><span class="n">j</span><span class="p">])</span>
<span class="p">{</span>
<span class="n">signal</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="n">SIGTSTP</span> <span class="o">?</span> <span class="n">stophandler</span> <span class="o">:</span> <span class="n">sighandler</span><span class="p">);</span>
<span class="n">siginterrupt</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cp">#endif</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// dereference 影响对于符号链接的处理</span>
<span class="c1">// 看到这里才发现自己的 ls 都没有考虑到符号链接</span>
<span class="k">if</span> <span class="p">(</span><span class="n">dereference</span> <span class="o">==</span> <span class="n">DEREF_UNDEFINED</span><span class="p">)</span>
<span class="n">dereference</span> <span class="o">=</span> <span class="p">((</span><span class="n">immediate_dirs</span>
<span class="o">||</span> <span class="n">indicator_style</span> <span class="o">==</span> <span class="n">classify</span>
<span class="o">||</span> <span class="n">format</span> <span class="o">==</span> <span class="n">long_format</span><span class="p">)</span>
<span class="o">?</span> <span class="n">DEREF_NEVER</span>
<span class="o">:</span> <span class="n">DEREF_COMMAND_LINE_SYMLINK_TO_DIR</span><span class="p">);</span>
<span class="cm">/* When using -R, initialize a data structure we'll use to</span>
<span class="cm"> detect any directory cycles. */</span>
<span class="c1">// 原有的注释已经写的很好了</span>
<span class="k">if</span> <span class="p">(</span><span class="n">recursive</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// active_dir_set 是为了防止循环的</span>
<span class="n">active_dir_set</span> <span class="o">=</span> <span class="n">hash_initialize</span> <span class="p">(</span><span class="n">INITIAL_TABLE_SIZE</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span>
<span class="n">dev_ino_hash</span><span class="p">,</span>
<span class="n">dev_ino_compare</span><span class="p">,</span>
<span class="n">dev_ino_free</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">active_dir_set</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="n">xalloc_die</span> <span class="p">();</span>
<span class="n">obstack_init</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">dev_ino_obstack</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// 看样子是和格式化输出相关的, 没细看</span>
<span class="n">format_needs_stat</span> <span class="o">=</span> <span class="n">sort_type</span> <span class="o">==</span> <span class="n">sort_time</span> <span class="o">||</span> <span class="n">sort_type</span> <span class="o">==</span> <span class="n">sort_size</span>
<span class="o">||</span> <span class="n">format</span> <span class="o">==</span> <span class="n">long_format</span>
<span class="o">||</span> <span class="n">print_scontext</span>
<span class="o">||</span> <span class="n">print_block_size</span><span class="p">;</span>
<span class="n">format_needs_type</span> <span class="o">=</span> <span class="p">(</span><span class="o">!</span> <span class="n">format_needs_stat</span>
<span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">recursive</span>
<span class="o">||</span> <span class="n">print_with_color</span>
<span class="o">||</span> <span class="n">indicator_style</span> <span class="o">!=</span> <span class="n">none</span>
<span class="o">||</span> <span class="n">directories_first</span><span class="p">));</span>
<span class="c1">// 和 --dired 选项有关, 略过</span>
<span class="k">if</span> <span class="p">(</span><span class="n">dired</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">//obstack_init 内存分配相关的</span>
<span class="n">obstack_init</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">dired_obstack</span><span class="p">);</span>
<span class="n">obstack_init</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">subdired_obstack</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// 当前文件夹下面的文件列表</span>
<span class="c1">// 'cwd_file' 指向 'struct fileinfo'</span>
<span class="c1">// 'cwd_n_alloc' 分配的 'struct fileinfo' 的个数</span>
<span class="c1">// 'cwd_n_used' 使用的 'struct fileinfo' 的个数</span>
<span class="n">cwd_n_alloc</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="n">cwd_file</span> <span class="o">=</span> <span class="n">xnmalloc</span> <span class="p">(</span><span class="n">cwd_n_alloc</span><span class="p">,</span> <span class="k">sizeof</span> <span class="o">*</span><span class="n">cwd_file</span><span class="p">);</span>
<span class="n">cwd_n_used</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">clear_files</span> <span class="p">();</span>
<span class="c1">// 给 ls 传入的文件数</span>
<span class="n">n_files</span> <span class="o">=</span> <span class="n">argc</span> <span class="o">-</span> <span class="n">i</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">n_files</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span>
<span class="c1">// 没有给出需要列出的目录/文件</span>
<span class="c1">// 默认使用当前目录</span>
<span class="p">{</span>
<span class="c1">// -d 选项决定着 immediate_dirs </span>
<span class="k">if</span> <span class="p">(</span><span class="n">immediate_dirs</span><span class="p">)</span>
<span class="c1">// 如果 -d 选项打开, 则将当前目录视为文件</span>
<span class="c1">// gobble_file 将文件添加到 cwd_file 链里</span>
<span class="n">gobble_file</span> <span class="p">(</span><span class="s">"."</span><span class="p">,</span> <span class="n">directory</span><span class="p">,</span> <span class="n">NOT_AN_INODE_NUMBER</span><span class="p">,</span> <span class="nb">true</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span>
<span class="k">else</span>
<span class="c1">// 否则的话将当前目录加入到需要列出的目录链里面</span>
<span class="n">queue_directory</span> <span class="p">(</span><span class="s">"."</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="c1">// 如果给出了目录/文件</span>
<span class="k">do</span>
<span class="n">gobble_file</span> <span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">],</span> <span class="n">unknown</span><span class="p">,</span> <span class="n">NOT_AN_INODE_NUMBER</span><span class="p">,</span> <span class="nb">true</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span>
<span class="k">while</span> <span class="p">(</span><span class="n">i</span> <span class="o">&lt;</span> <span class="n">argc</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">cwd_n_used</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// 对文件进行排序, 我自己实现的 ls 里面由于是直接使用 printf 的</span>
<span class="c1">// 所以列出的文件/目录信息是乱序的, 自己偷懒了 :)</span>
<span class="n">sort_files</span> <span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">immediate_dirs</span><span class="p">)</span>
<span class="c1">// 如果没有给出 -d 选项, 则将目录从需要列出的链里移除, 并添加到</span>
<span class="c1">// pending_dirs 里</span>
<span class="n">extract_dirs_from_files</span> <span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
<span class="cm">/* 'cwd_n_used' might be zero now. */</span>
<span class="p">}</span>
<span class="cm">/* In the following if/else blocks, it is sufficient to test 'pending_dirs'</span>
<span class="cm"> (and not pending_dirs-&gt;name) because there may be no markers in the queue</span>
<span class="cm"> at this point. A marker may be enqueued when extract_dirs_from_files is</span>
<span class="cm"> called with a non-empty string or via print_dir. */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">cwd_n_used</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// 打印出文件信息</span>
<span class="n">print_current_files</span> <span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pending_dirs</span><span class="p">)</span>
<span class="n">DIRED_PUTCHAR</span> <span class="p">(</span><span class="sc">'\n'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">n_files</span> <span class="o">&lt;=</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">pending_dirs</span> <span class="o">&amp;&amp;</span> <span class="n">pending_dirs</span><span class="o">-&gt;</span><span class="n">next</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="c1">// 和 ls 的打印方式有关, 当给出了两个以上的路径并且没有打开 -d 选项,</span>
<span class="c1">// 并且其中有一个是目录的话, 就要打印出目录名</span>
<span class="c1">// 这点自己的程序里也是考虑到了的</span>
<span class="n">print_dir_name</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">pending_dirs</span><span class="p">)</span>
<span class="c1">// 遍历 pending_dirs</span>
<span class="p">{</span>
<span class="n">thispend</span> <span class="o">=</span> <span class="n">pending_dirs</span><span class="p">;</span>
<span class="n">pending_dirs</span> <span class="o">=</span> <span class="n">pending_dirs</span><span class="o">-&gt;</span><span class="n">next</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">LOOP_DETECT</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">thispend</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* thispend-&gt;name == NULL means this is a marker entry</span>
<span class="cm"> indicating we've finished processing the directory.</span>
<span class="cm"> Use its dev/ino numbers to remove the corresponding</span>
<span class="cm"> entry from the active_dir_set hash table. */</span>
<span class="k">struct</span> <span class="n">dev_ino</span> <span class="n">di</span> <span class="o">=</span> <span class="n">dev_ino_pop</span> <span class="p">();</span>
<span class="k">struct</span> <span class="n">dev_ino</span> <span class="o">*</span><span class="n">found</span> <span class="o">=</span> <span class="n">hash_delete</span> <span class="p">(</span><span class="n">active_dir_set</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">di</span><span class="p">);</span>
<span class="cm">/* ASSERT_MATCHING_DEV_INO (thispend-&gt;realname, di); */</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">found</span><span class="p">);</span>
<span class="n">dev_ino_free</span> <span class="p">(</span><span class="n">found</span><span class="p">);</span>
<span class="n">free_pending_ent</span> <span class="p">(</span><span class="n">thispend</span><span class="p">);</span>
<span class="k">continue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// 如果打开了 -R, print_dir 会有相应的处理</span>
<span class="c1">// 调用 extract_dirs_from_files, 将文件夹加入到 pending_dirs</span>
<span class="c1">//</span>
<span class="c1">// print_dir 的大概过程是先将文件夹里的文件添加到 cwd_files</span>
<span class="c1">// 里然后调用 print_current_files 进行打印</span>
<span class="c1">//</span>
<span class="c1">// print_current_files 又会很据选项调用相应的打印函数, 比如对于</span>
<span class="c1">// -l 选项就会调用 print_long_format 函数</span>
<span class="c1">// 这样可以进行很好的格式化输出</span>
<span class="c1">// 我自己的实现里面是直接调用 printf, 所以没法保证同一文件夹里的</span>
<span class="c1">// 文件的相应栏保持对齐</span>
<span class="n">print_dir</span> <span class="p">(</span><span class="n">thispend</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> <span class="n">thispend</span><span class="o">-&gt;</span><span class="n">realname</span><span class="p">,</span>
<span class="n">thispend</span><span class="o">-&gt;</span><span class="n">command_line_arg</span><span class="p">);</span>
<span class="n">free_pending_ent</span> <span class="p">(</span><span class="n">thispend</span><span class="p">);</span>
<span class="n">print_dir_name</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// 看名字应该和高亮显示相关, 略过</span>
<span class="k">if</span> <span class="p">(</span><span class="n">print_with_color</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">j</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">used_color</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* Skip the restore when it would be a no-op, i.e.,</span>
<span class="cm"> when left is "\033[" and right is "m". */</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">color_indicator</span><span class="p">[</span><span class="n">C_LEFT</span><span class="p">].</span><span class="n">len</span> <span class="o">==</span> <span class="mi">2</span>
<span class="o">&amp;&amp;</span> <span class="n">memcmp</span> <span class="p">(</span><span class="n">color_indicator</span><span class="p">[</span><span class="n">C_LEFT</span><span class="p">].</span><span class="n">string</span><span class="p">,</span> <span class="s">"</span><span class="se">\033</span><span class="s">["</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="o">&amp;&amp;</span> <span class="n">color_indicator</span><span class="p">[</span><span class="n">C_RIGHT</span><span class="p">].</span><span class="n">len</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">&amp;&amp;</span> <span class="n">color_indicator</span><span class="p">[</span><span class="n">C_RIGHT</span><span class="p">].</span><span class="n">string</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="sc">'m'</span><span class="p">))</span>
<span class="n">restore_default_color</span> <span class="p">();</span>
<span class="p">}</span>
<span class="n">fflush</span> <span class="p">(</span><span class="n">stdout</span><span class="p">);</span>
<span class="cm">/* Restore the default signal handling. */</span>
<span class="cp">#if SA_NOCLDSTOP</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nsigs</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sigismember</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">caught_signals</span><span class="p">,</span> <span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">]))</span>
<span class="n">signal</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">SIG_DFL</span><span class="p">);</span>
<span class="cp">#else</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">nsigs</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">caught_sig</span><span class="p">[</span><span class="n">j</span><span class="p">])</span>
<span class="n">signal</span> <span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">SIG_DFL</span><span class="p">);</span>
<span class="cp">#endif</span>
<span class="cm">/* Act on any signals that arrived before the default was restored.</span>
<span class="cm"> This can process signals out of order, but there doesn't seem to</span>
<span class="cm"> be an easy way to do them in order, and the order isn't that</span>
<span class="cm"> important anyway. */</span>
<span class="k">for</span> <span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="n">stop_signal_count</span><span class="p">;</span> <span class="n">j</span><span class="p">;</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span>
<span class="n">raise</span> <span class="p">(</span><span class="n">SIGSTOP</span><span class="p">);</span>
<span class="n">j</span> <span class="o">=</span> <span class="n">interrupt_signal</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">j</span><span class="p">)</span>
<span class="n">raise</span> <span class="p">(</span><span class="n">j</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// 和 --dired 有关, 略过</span>
<span class="k">if</span> <span class="p">(</span><span class="n">dired</span><span class="p">)</span>
<span class="p">{</span>
<span class="cm">/* No need to free these since we're about to exit. */</span>
<span class="n">dired_dump_obstack</span> <span class="p">(</span><span class="s">"//DIRED//"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">dired_obstack</span><span class="p">);</span>
<span class="n">dired_dump_obstack</span> <span class="p">(</span><span class="s">"//SUBDIRED//"</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">subdired_obstack</span><span class="p">);</span>
<span class="n">printf</span> <span class="p">(</span><span class="s">"//DIRED-OPTIONS// --quoting-style=%s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
<span class="n">quoting_style_args</span><span class="p">[</span><span class="n">get_quoting_style</span> <span class="p">(</span><span class="n">filename_quoting_options</span><span class="p">)]);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">LOOP_DETECT</span><span class="p">)</span>
<span class="c1">// 如果打开了 -R 选项, 结束时需要将 active_dir_set 回收</span>
<span class="p">{</span>
<span class="n">assert</span> <span class="p">(</span><span class="n">hash_get_n_entries</span> <span class="p">(</span><span class="n">active_dir_set</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">hash_free</span> <span class="p">(</span><span class="n">active_dir_set</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">exit</span> <span class="p">(</span><span class="n">exit_status</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
</body>
</hmtl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment