Compare commits
7 Commits
dc16810028
...
f1d2359391
| Author | SHA1 | Date | |
|---|---|---|---|
| f1d2359391 | |||
| b87adb2748 | |||
| 2046b46340 | |||
| 50c0c08242 | |||
| d27b878e58 | |||
| 2e3b8c3289 | |||
| 8d4d3be103 |
8
README
8
README
@@ -47,12 +47,12 @@ The attributes section follows the text section. The attributes section ends
|
||||
with a single newline. Text including and following a hash in the attributes
|
||||
section will be ignoroed.
|
||||
|
||||
The command section follows the attributes section. The command section is
|
||||
The content section follows the attributes section. The content section is
|
||||
run as a single argument following the invocation `$ sh -c`, like the C
|
||||
standard library's system(3). Each line in the command section is preceded by
|
||||
a horizontal tab, which is removed from the argument; if a line in the command
|
||||
standard library's system(3). Each line in the content section is preceded by
|
||||
a horizontal tab, which is removed from the argument; if a line in the content
|
||||
section is not preceded by a tab, the omission is considered a syntax error (a
|
||||
"naked line") and menu(1) exits unsuccessfully. The command section ends with
|
||||
"naked line") and menu(1) exits unsuccessfully. The content section ends with
|
||||
two consecutive newlines.
|
||||
|
||||
## POSIX systems
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!usr/bin/env menu
|
||||
|
||||
$ echo Hello, world.
|
||||
# ^^^ Text VVV Command
|
||||
# ^^^ Text VVV Content
|
||||
echo Hello, world.
|
||||
|
||||
$ cat Makefile
|
||||
|
||||
@@ -4,13 +4,14 @@ import re, sys, xml.etree.ElementTree as ET
|
||||
ET.register_namespace("", "http://www.w3.org/2005/Atom")
|
||||
ET.register_namespace("media", "http://search.yahoo.com/mrss/")
|
||||
ET.register_namespace("yt", "http://www.youtube.com/xml/schemas/2015")
|
||||
def sortby(entry):
|
||||
return entry.findall("{http://www.w3.org/2005/Atom}published")[0].text
|
||||
macrofeed = ET.Element('feed')
|
||||
macrofeed.extend(
|
||||
sorted([
|
||||
entry
|
||||
# Split the input by file.
|
||||
# Split the input by file. This relies on a typical <XML /> tag
|
||||
# starting a file. Theoretically this assumption could be wrong,
|
||||
# but in that case the XML parser would break before
|
||||
# ytfeed.aggregate could spit malformed output.
|
||||
for feed in re.split(r'<\?xml.*?\?>', sys.stdin.read())[1:]
|
||||
# Get the entries out of each file.
|
||||
for entry
|
||||
@@ -18,9 +19,8 @@ macrofeed.extend(
|
||||
.findall("{http://www.w3.org/2005/Atom}entry")
|
||||
],
|
||||
# Gets the publication date and sorts the entries from old to new.
|
||||
key = lambda entry
|
||||
key = lambda entry # (this is a text sort but it still works)
|
||||
: entry.findall("{http://www.w3.org/2005/Atom}published")[0].text,
|
||||
reverse = False # toggle this to switch the order
|
||||
)
|
||||
)
|
||||
print(ET.tostring(macrofeed, encoding="unicode"))
|
||||
|
||||
@@ -20,7 +20,7 @@ for entry in root.findall("{http://www.w3.org/2005/Atom}entry"):
|
||||
+ f("%-22s - ", entry, "author/name")
|
||||
+ f("%s", entry, "title") + "\n\n"
|
||||
# Command
|
||||
+ "\t" + "ytfeed.browse-entry <<EOF | ../menu" + "\n"
|
||||
+ "\t" + "ytfeed.browse-entry <<EOF | menu" + "\n"
|
||||
+ "\t" + ET.tostring(entry, encoding="unicode")
|
||||
.replace("\n", "\n\t").rstrip() + "\n"
|
||||
+ "\tEOF",
|
||||
|
||||
@@ -9,8 +9,11 @@ directory = sys.argv[1]
|
||||
for f in os.listdir(directory):
|
||||
file_name = os.path.join(directory, f)
|
||||
if os.path.isfile(file_name) and f[-4:] == ".xml":
|
||||
tree = ET.parse(file_name)
|
||||
root = tree.getroot()
|
||||
try: tree = ET.parse(file_name)
|
||||
except ET.ParseError as e:
|
||||
print("%s: %s: %s" % (sys.argv[0], file_name, e), file = sys.stderr)
|
||||
continue
|
||||
else: root = tree.getroot()
|
||||
try:
|
||||
channels += [
|
||||
"%s\n\n" % root.find('{http://www.w3.org/2005/Atom}title').text
|
||||
|
||||
@@ -13,9 +13,12 @@ while test -n "$2"; do
|
||||
else curl=false
|
||||
fi
|
||||
filename="$(printf '%s/%s.xml\n' "$directory" "$2")"
|
||||
if ! $curl "$xml_url_prefix""$2" >"$filename"
|
||||
then rm -f "$filename"
|
||||
else printf '%s\n' "$filename"
|
||||
$curl "$xml_url_prefix""$2" >"$filename".new
|
||||
if ! grep '<title>' <"$filename".new | head -n 1 \
|
||||
| grep 404 >/dev/null 2>&1
|
||||
then mv "$filename".new "$filename" \
|
||||
&& printf '%s\n' "$filename"
|
||||
fi
|
||||
rm -f "$filename".new
|
||||
shift
|
||||
done
|
||||
|
||||
24
menu.rs
24
menu.rs
@@ -59,7 +59,7 @@ fn print_entries(entries: &[Entry]) {
|
||||
|
||||
eprintln!("");
|
||||
for (index, entry) in entries.iter().enumerate() {
|
||||
eprint!(
|
||||
eprintln!(
|
||||
"[{:>index_len$}]: {}",
|
||||
index + 1,
|
||||
entry.text,
|
||||
@@ -82,9 +82,7 @@ fn main() -> ExitCode {
|
||||
}
|
||||
Ok(file) => Box::new(BufReader::new(file)),
|
||||
}
|
||||
} else {
|
||||
Box::new(io::stdin().lock())
|
||||
};
|
||||
} else { Box::new(io::stdin().lock()) };
|
||||
let user_input: Box<dyn BufRead> = if argv.len() <= 1 {
|
||||
match File::open("/dev/tty") {
|
||||
Err(e) => {
|
||||
@@ -92,9 +90,7 @@ fn main() -> ExitCode {
|
||||
}
|
||||
Ok(file) => Box::new(BufReader::new(file)),
|
||||
}
|
||||
} else {
|
||||
Box::new(io::stdin().lock())
|
||||
}; // ...Oops! I did it again.
|
||||
} else { Box::new(io::stdin().lock()) }; // ...Oops! I did it again.
|
||||
|
||||
// Parser
|
||||
{
|
||||
@@ -114,11 +110,11 @@ fn main() -> ExitCode {
|
||||
}
|
||||
}
|
||||
State::Text => {
|
||||
entry.text = line.clone() + "\n";
|
||||
entry.text = line.clone();
|
||||
state = State::Attributes;
|
||||
}
|
||||
State::Attributes => {
|
||||
entry.attr = line.clone() + "\n";
|
||||
entry.attr = line.clone();
|
||||
state = State::Content;
|
||||
}
|
||||
State::Content => match line.chars().next() {
|
||||
@@ -160,10 +156,11 @@ fn main() -> ExitCode {
|
||||
if line != "" {
|
||||
match line.parse::<usize>() {
|
||||
Err(e) => {
|
||||
return error(&argv[0], &line, &e);
|
||||
eprintln!("{}: Could not parse selection (try 0..{})",
|
||||
argv[0], entries.len());
|
||||
}
|
||||
Ok(n) => {
|
||||
if n != 0 {
|
||||
if n != 0 && n <= entries.len() {
|
||||
match Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(entries[n - 1].cont.clone())
|
||||
@@ -177,8 +174,9 @@ fn main() -> ExitCode {
|
||||
Ok(_) => { print_entries(&entries); }
|
||||
},
|
||||
}
|
||||
}
|
||||
if n == 0 || exit_on_selection {
|
||||
} else if n > entries.len() {
|
||||
eprintln!("{}: Selection out of range", argv[0]);
|
||||
} else if n == 0 || exit_on_selection {
|
||||
return ExitCode::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user