diff --git a/README.md b/README.md index ed2b98e..777a134 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,10 @@ console.log(devpun.list("react")); // returns an array of all react jokes ```bash $ devpun [options] ``` +or +```bash +$ ./devpun.py [options] +``` ### Options diff --git a/devpun.py b/devpun.py new file mode 100644 index 0000000..cced337 --- /dev/null +++ b/devpun.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +import argparse +import collections +import json +import random +import sys +from typing import Dict, List, Union + + +def main() -> int: + parser: argparse.ArgumentParser = argparse.ArgumentParser() + action: argparse._MutuallyExclusiveGroup = parser.add_mutually_exclusive_group() + action.add_argument( + "--count", + "-c", + dest="action", + type=int, + help="Show up to N matching jokes", + metavar="N", + ) + action.add_argument( + "--list", + "--list-jokes", + "-l", + dest="action", + action="store_const", + const="list", + help="List all matching jokes, instead of choosing one at random", + ) + action.add_argument( + "--list-tags", + "-T", + dest="action", + action="store_const", + const="list_tags", + help="List all available tags with corresponding joke count, then exit.", + ) + parser.add_argument( + "--tag", + "-t", + nargs=1, + action="append", + dest="tags", + help="Filter by tag (ANDed if repeated)", + default=[], + ) + opts: argparse.Namespace = parser.parse_args() + + joke_list: List[Dict[str, Union[str, List[str]]]] = json.load( + open("jokes.json", "r") + ) + + if opts.action == "list_tags": + tag_list: Dict[str, int] = collections.defaultdict(int) + for j in joke_list: + for t in j.get("tags", []): + tag_list[t] += 1 + print("\n".join(["%3d %s" % (tag_list[t], t) for t in sorted(tag_list.keys())])) + return 0 + + if opts.tags: + for tag in opts.tags: + joke_list = filter(lambda j: tag[0] in j.get("tags", []), joke_list) + + # Shuffle, and also boil it back down from a filter + joke_list: List[Dict[str, Union[str, List[str]]]] = list(joke_list) + random.shuffle(joke_list) + + if not joke_list: + print("No matching jokes found.") + return 1 + + if opts.action != "list": + count: int = 1 + if isinstance(opts.action, int): + count: int = opts.action + joke_list = joke_list[:count] + + i: int + j: Dict[str, Union[str, List[str]]] + for i, j in enumerate(joke_list): + if i: + # Add a blank line between jokes. + print("") + + if j.get("text", None): + print(j["text"]) + else: + print(f"Q. {j['question']}") + print(f"A. {j['answer']}") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/jokes.json b/jokes.json index 8402b0c..c54f168 100644 --- a/jokes.json +++ b/jokes.json @@ -1,193 +1,296 @@ [ { - "text": "q. How do you comfort a JavaScript bug? a. You console it.", - "question": "How do you comfort a JavaScript bug?", "answer": "You console it.", "author": "elijahmanor", "created": "09/06/2013", - "tags": ["javascript"] + "question": "How do you comfort a JavaScript bug?", + "tags": [ + "javascript" + ], + "text": "q. How do you comfort a JavaScript bug? a. You console it." }, { - "text": "q. Why did the child component have such great self-esteem? a. Because its parent kept giving it `props`!", - "question": "Why did the child component have such great self-esteem?", "answer": "Because its parent kept giving it `props`!", "author": "elijahmanor", "created": "05/22/2017", - "tags": ["javascript", "react"] + "question": "Why did the child component have such great self-esteem?", + "tags": [ + "javascript", + "react" + ], + "text": "q. Why did the child component have such great self-esteem? a. Because its parent kept giving it `props`!" }, { - "text": "q. Why do C# and Java developers keep breaking their keyboards? a. Because they use a strongly typed language!", - "question": "Why do C# and Java developers keep breaking their keyboards", "answer": "Because they use a strongly typed language", "author": "elijahmanor", "created": "09/23/2013", - "tags": ["javascript", "java", "c#"] + "question": "Why do C# and Java developers keep breaking their keyboards", + "tags": [ + "javascript", + "java", + "c#" + ], + "text": "q. Why do C# and Java developers keep breaking their keyboards? a. Because they use a strongly typed language!" }, { - "text": "q. Why did the functional component feel lost? a. Because it didn't know what `state` it was in!", - "question": "Why did the functional component feel lost?", "answer": "Because it didn't know what `state` it was in!", "author": "elijahmanor", "created": "05/22/2017", - "tags": ["javascript", "react"] + "question": "Why did the functional component feel lost?", + "tags": [ + "javascript", + "react" + ], + "text": "q. Why did the functional component feel lost? a. Because it didn't know what `state` it was in!" }, { - "text": "q. Why was the JavaScript developer sad? a. Because he didn't Node how to Express himself!", - "question": "Why was the JavaScript developer sad?", "answer": "Because he didn't Node how to Express himself!", "author": "elijahmanor", "created": "09/10/2013", - "tags": ["javascript", "node"] + "question": "Why was the JavaScript developer sad?", + "tags": [ + "javascript", + "node" + ], + "text": "q. Why was the JavaScript developer sad? a. Because he didn't Node how to Express himself!" }, { - "text": "q. Why did the developer go broke? a. Because he used up all his cache!", - "question": "Why did the developer go broke?", "answer": "Because he used up all his cache!", "author": "elijahmanor", "created": "09/17/2013", - "tags": [] + "question": "Why did the developer go broke?", + "tags": [], + "text": "q. Why did the developer go broke? a. Because he used up all his cache!" }, { - "text": "q. Why did the React Higher Order Component give up? a. Because it sur-rendered to the prop-aganda!", - "question": "Why did the React Higher Order Component give up?", "answer": "Because it sur-rendered to the prop-aganda!", "author": "elijahmanor", "created": "10/31/2017", - "tags": ["javascript", "react"] + "question": "Why did the React Higher Order Component give up?", + "tags": [ + "javascript", + "react" + ], + "text": "q. Why did the React Higher Order Component give up? a. Because it sur-rendered to the prop-aganda!" }, { - "text": "When a JavaScript date has gone bad, \"Don't call me, I'll callback you. I promise!\"", "author": "elijahmanor", "created": "09/09/2013", - "tags": ["javascript"] + "tags": [ + "javascript" + ], + "text": "When a JavaScript date has gone bad, \"Don't call me, I'll callback you. I promise!\"" }, { - "text": "q. Why did the react class component feel relieved? a. Because it was now off the hook.", - "question": "Why did the react class component feel relieved?", "answer": "Because it was now off the hook.", "author": "elijahmanor", "created": "11/27/2018", - "tags": ["javascript", "react"] + "question": "Why did the react class component feel relieved?", + "tags": [ + "javascript", + "react" + ], + "text": "q. Why did the react class component feel relieved? a. Because it was now off the hook." }, { - "text": "q. Why did the react developer have an addiction? a. Because they were completely hooked on the hooks proposal.", - "question": "Why did the react developer have an addiction?", "answer": "Because they were completely hooked on the hooks proposal.", "author": "elijahmanor", "created": "11/27/2018", - "tags": ["javascript", "react"] + "question": "Why did the react developer have an addiction?", + "tags": [ + "javascript", + "react" + ], + "text": "q. Why did the react developer have an addiction? a. Because they were completely hooked on the hooks proposal." }, { - "text": "q. What does a React proposal mean? a. It means to swallow something hook, line and sinker.", - "question": "What does a React proposal mean?", "answer": "It means to swallow something hook, line and sinker.", "author": "elijahmanor", "created": "11/27/2018", - "tags": ["javascript", "react"] + "question": "What does a React proposal mean?", + "tags": [ + "javascript", + "react" + ], + "text": "q. What does a React proposal mean? a. It means to swallow something hook, line and sinker." }, { - "text": "q. Why was the react developer late to everything? a. Because they were playing hooky with the hooks proposal", - "question": "Why was the react developer late to everything?", "answer": "Because they were playing hooky with the hooks proposal.", "author": "elijahmanor", "created": "11/27/2018", - "tags": ["javascript", "react"] + "question": "Why was the react developer late to everything?", + "tags": [ + "javascript", + "react" + ], + "text": "q. Why was the react developer late to everything? a. Because they were playing hooky with the hooks proposal" }, { - "text": "q. Why couldn’t the React component understand the joke? a. Because it didn’t get the context.", - "question": "Why couldn’t the React component understand the joke?", - "answer": "Because it didn’t get the context.", + "answer": "Because it didn\u2019t get the context.", "author": "elijahmanor", "created": "11/27/2018", - "tags": ["javascript", "react"] + "question": "Why couldn\u2019t the React component understand the joke?", + "tags": [ + "javascript", + "react" + ], + "text": "q. Why couldn\u2019t the React component understand the joke? a. Because it didn\u2019t get the context." }, { - "text": "Dev1 saw a strange JavaScript function & asked, \"What is this?\". Dev2 responded, \"I don't know. I would've called you, but I was in a bind\"", "author": "elijahmanor", "created": "09/09/2013", - "tags": ["javascript"] + "tags": [ + "javascript" + ], + "text": "Dev1 saw a strange JavaScript function & asked, \"What is this?\". Dev2 responded, \"I don't know. I would've called you, but I was in a bind\"" }, { - "text": "Two JavaScript developers walked into the variable `bar`. Ouch!", "author": "elijahmanor", "created": "09/10/2013", - "tags": ["javascript"] + "tags": [ + "javascript" + ], + "text": "Two JavaScript developers walked into the variable `bar`. Ouch!" }, { - "text": "q. Why did Jason cover himself with bubble wrap? a. Because he wanted to make a cross-domain JSONP request.", - "question": "Why did Jason cover himself with bubble wrap?", "answer": "Because he wanted to make a cross-domain JSONP request", "author": "elijahmanor", "created": "09/11/2013", - "tags": ["javascript"] + "question": "Why did Jason cover himself with bubble wrap?", + "tags": [ + "javascript" + ], + "text": "q. Why did Jason cover himself with bubble wrap? a. Because he wanted to make a cross-domain JSONP request." }, { - "text": "q. Why did the software company hire drama majors from Starbucks? a. Because they needed JavaScript experts!", - "question": "Why did the software company hire drama majors from Starbucks?", "answer": "Because they needed JavaScript experts!", "author": "elijahmanor", "created": "09/12/2013", - "tags": ["javascript"] + "question": "Why did the software company hire drama majors from Starbucks?", + "tags": [ + "javascript" + ], + "text": "q. Why did the software company hire drama majors from Starbucks? a. Because they needed JavaScript experts!" }, { - "text": "q. Why did the CoffeeScript developer keep getting lost? a. Because he couldn't find his source without a map!", - "question": "Why did the CoffeeScript developer keep getting lost?", "answer": "Because he couldn't find his source without a map!", "author": "elijahmanor", "created": "09/13/2013", - "tags": ["javascript", "coffeescript"] + "question": "Why did the CoffeeScript developer keep getting lost?", + "tags": [ + "javascript", + "coffeescript" + ], + "text": "q. Why did the CoffeeScript developer keep getting lost? a. Because he couldn't find his source without a map!" }, { - "text": "q. What do you call __proto__? a. Dunder proto q. Michael Scott was the regional manager where? a. __mifflin__", - "question": "What do you call __proto__? Dunder proto. Michael Scott was the regional manager where?", "answer": "__mifflin__", "author": "elijahmanor", "created": "09/16/2013", - "tags": ["javascript"] + "question": "What do you call __proto__? Dunder proto. Michael Scott was the regional manager where?", + "tags": [ + "javascript" + ], + "text": "q. What do you call __proto__? a. Dunder proto q. Michael Scott was the regional manager where? a. __mifflin__" }, { - "text": "q. How did the doctor revive the developer? a. The dev wasn't responsive so the doc picked him up by his bootstraps!", - "question": "How did the doctor revive the developer?", "answer": "The dev wasn't responsive so the doc picked him up by his bootstraps!", "author": "elijahmanor", "created": "09/16/2013", - "tags": ["css"] + "question": "How did the doctor revive the developer?", + "tags": [ + "css" + ], + "text": "q. How did the doctor revive the developer? a. The dev wasn't responsive so the doc picked him up by his bootstraps!" }, { - "text": "q. Why did the C# developer fall asleep? a. Because he didn't like Java.", - "question": "Why did the C# developer fall asleep?", "answer": "Because he didn't like Java.", "author": "elijahmanor", "created": "09/18/2013", - "tags": ["java", "c#"] + "question": "Why did the C# developer fall asleep?", + "tags": [ + "java", + "c#" + ], + "text": "q. Why did the C# developer fall asleep? a. Because he didn't like Java." }, { - "text": - "q. Why did the JavaScript boxer goto the chiropractor? a. Because his backbone was angular from a knockout and required attention!", - "question": "Why did the JavaScript boxer goto the chiropractor?", - "answer": - "Because his backbone was angular from a knockout and required attention!", + "answer": "Because his backbone was angular from a knockout and required attention!", "author": "elijahmanor", "created": "09/19/2013", - "tags": ["javascript", "knockout", "backbone"] + "question": "Why did the JavaScript boxer goto the chiropractor?", + "tags": [ + "javascript", + "knockout", + "backbone" + ], + "text": "q. Why did the JavaScript boxer goto the chiropractor? a. Because his backbone was angular from a knockout and required attention!" }, { - "text": - "q. How did the web dev hurt Comic Sans feelings? a. Once he saw the font he quickly changed to Open Sans and exclaimed \"In your @font-face!\"", - "question": "How did the web dev hurt Comic Sans feelings?", - "answer": - "Once he saw the font he quickly changed to Open Sans and exclaimed \"In your @font-face!\"", + "answer": "Once he saw the font he quickly changed to Open Sans and exclaimed \"In your @font-face!\"", "author": "elijahmanor", "created": "09/20/2013", - "tags": ["css"] + "question": "How did the web dev hurt Comic Sans feelings?", + "tags": [ + "css" + ], + "text": "q. How did the web dev hurt Comic Sans feelings? a. Once he saw the font he quickly changed to Open Sans and exclaimed \"In your @font-face!\"" }, { - "text": - "q. Why was Ember.js turning red? a. Because it was EMBERrassed for not remEMBERing its route home!", - "question": "Why was Ember.js turning red?", "answer": "Because it was EMBERrassed for not remEMBERing its route home!", "author": "elijahmanor", "created": "09/24/2013", - "tags": ["javascript", "ember"] + "question": "Why was Ember.js turning red?", + "tags": [ + "javascript", + "ember" + ], + "text": "q. Why was Ember.js turning red? a. Because it was EMBERrassed for not remEMBERing its route home!" + }, + { + "answer": "It'll be a real pain in their ASP!", + "author": "BMDan", + "created": "2019-05-01", + "question": "Why is Microsoft afraid of Python as a Web language?", + "tags": [ + "python", + "asp" + ] + }, + { + "answer": "No double-inheritance.", + "author": "BMDan", + "created": "2019-05-01", + "question": "Why did Java stop having children after the first arrived?", + "tags": [ + "java" + ] + }, + { + "answer": "Functools partials, a few lambdas, most def.", + "author": "BMDan", + "created": "2019-05-01", + "question": "How do the cool kids write their programs' functions nowadays?", + "tags": [ + "python" + ] + }, + { + "answer": "__mifflin__", + "author": "BMDan (based on elijahmanor)", + "created": "2019-05-01", + "question": "Where was Michael Scott the regional manager?", + "tags": [ + "python" + ] + }, + { + "answer": "from __future__ import...", + "author": "BMDan", + "created": "2019-05-01", + "question": "Is there any way to see the hot new movie if it hasn't been released in your country yet?", + "tags": [ + "python" + ] } ]