├── .gitignore ├── README.md ├── requirements.txt ├── setup.py └── wiki ├── client.py ├── functions.py └── wiki_lexer.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | dist 3 | build 4 | wiki_terminal.egg-info 5 | *.pyc 6 | venv/ 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wiki_terminal 2 | --- 3 | This will enable you wiki in the terminal. 4 | 5 | ## Install: 6 | you can install it by: 7 | `python install setup.py` 8 | 9 | or simply: 10 | `pip install wiki_terminal` 11 | 12 | ## Help: 13 | * `help`for help 14 | 15 | * `summary arg`to get summary about the arg 16 | 17 | * `search arg`to search arg on wiki 18 | 19 | * `random s(summary)`to get a random tittle (you can get summary about it if you want.) 20 | 21 | * `geosearch latitude longitude (radius)` Do a wikipedia geo search for latitude and longitude using. 22 | 23 | ## Version: 24 | * Version 1.0.0 basic function built 25 | * Version 1.0.1 the geosearch function is added 26 | * Version 1.1.0 the keyword-highlight function is added 27 | * version 1.1.1 the search function bug fixed and history function added 28 | * version 1.2.0 rewrite wiki_terminal by using prompt-toolkit 29 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.4.1 2 | prompt-toolkit==0.54 3 | Pygments==2.0.2 4 | requests==2.8.1 5 | six==1.10.0 6 | termcolor==1.1.0 7 | wcwidth==0.1.5 8 | wheel==0.24.0 9 | wikipedia==1.4.0 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | __author__ = 'cm' 2 | from setuptools import setup, find_packages, Extension 3 | 4 | setup(name='wiki_terminal', 5 | version='1.2.0', 6 | description="This script will enable you use wikipedia in terminal.", 7 | long_description=""" 8 | Install: 9 | you can install it by python install setup.py 10 | Help: 11 | use help for help 12 | summary arg to get summary about the arg 13 | search arg to search arg on wiki 14 | random s(summary)to get a random tittle (you can get summary about it if you want.) 15 | geosearch latitude longitude (radius) Do a wikipedia geo search for latitude and longitude using. 16 | Version: 17 | Version 1.0.0 basic function built\n 18 | Version 1.0.1 the geosearch function is added\n 19 | version 1.1.0 the keyword-highlight function is added\n 20 | version 1.1.1 the search function bug fixed and history function added\n 21 | version 1.2.0 rewrite wiki_terminal using prompt-toolkit\n 22 | """, 23 | keywords='python wikipedia terminal', 24 | author='cm', 25 | author_email='jason0916phoenix@gmail.com', 26 | url='https://github.com/JASON0916/wiki_terminal', 27 | license='MIT', 28 | packages=find_packages(exclude=['tests']), 29 | include_package_data=True, 30 | zip_safe=False, 31 | install_requires=[ 32 | 'termcolor', 'wikipedia', 33 | ], 34 | classifiers=[ 35 | 'Programming Language :: Python :: 2.7', 36 | ], 37 | entry_points={ 38 | 'console_scripts': [ 39 | 'wikipedia = wiki.client:main', 40 | ] 41 | }, 42 | ) 43 | -------------------------------------------------------------------------------- /wiki/client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import unicode_literals 5 | from prompt_toolkit import prompt 6 | from prompt_toolkit.history import InMemoryHistory 7 | from prompt_toolkit.contrib.completers import WordCompleter 8 | from pygments.style import Style 9 | from pygments.token import Token 10 | from wiki_lexer import WikiLexer 11 | from pygments.styles.default import DefaultStyle 12 | from functions import QueryManager 13 | 14 | wiki_completer = WordCompleter([ 15 | 'summary', 16 | 'search', 17 | 'random', 18 | 'geosearch', 19 | 'quit', 20 | 'help' 21 | ], meta_dict={ 22 | 'summary': 'used to get summary of a word', 23 | 'search': 'used to search for a certain word.', 24 | 'random': 'used to have a title even show \ 25 | its summary randomly.', 26 | 'geosearch': 'used to find out what happend\ 27 | at a certain location or in the\ 28 | range of radius.' 29 | }, ignore_case=True) 30 | 31 | 32 | class DocumentStyle(Style): 33 | styles = { 34 | Token.Menu.Completions.Completion.Current: 'bg:#00aaaa #000000', 35 | Token.Menu.Completions.Completion: 'bg:#008888 #ffffff', 36 | Token.Menu.Completions.ProgressButton: 'bg:#003333', 37 | Token.Menu.Completions.ProgressBar: 'bg:#00aaaa', 38 | } 39 | styles.update(DefaultStyle.styles) 40 | 41 | 42 | def main(): 43 | history = InMemoryHistory() 44 | manager = QueryManager() 45 | while True: 46 | try: 47 | input = prompt('>>> ', lexer=WikiLexer, completer=wiki_completer, 48 | style=DocumentStyle, history=history, 49 | display_completions_in_columns=True) 50 | 51 | if not input or input.lower() == 'quit': 52 | print 'See you.' 53 | break 54 | else: 55 | func, args = input.split()[0], input.split()[1:] 56 | try: 57 | getattr(manager, func)(args) 58 | except AttributeError as error: 59 | print 'No function: %s' %func 60 | 61 | except KeyboardInterrupt as stop: 62 | print 'See you.' 63 | break 64 | 65 | 66 | 67 | if __name__ == '__main__': 68 | main() 69 | -------------------------------------------------------------------------------- /wiki/functions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import wikipedia 4 | from termcolor import colored, cprint 5 | 6 | 7 | class BaseManager(object): 8 | """BaseManager of the QueryManager, mainly to make a singleton.""" 9 | _state = {} 10 | 11 | def __new__(cls, *args, **kwargs): 12 | ob = super(BaseManager, cls).__new__(cls, *args, **kwargs) 13 | ob.__dict__ = cls._state 14 | return ob 15 | 16 | 17 | class QueryManager(BaseManager): 18 | """Manager to manage the query send by the terminal.""" 19 | 20 | __all__ = ['search', 'summary', 'geosearch', 'random', 'help'] 21 | 22 | @staticmethod 23 | def w_print(words, words_color, key_word=[], key_word_color='green'): 24 | """used to proceed the query result and print it in format.""" 25 | if key_word is not []: 26 | key_word = [str(key_words).lower() for key_words in key_word] 27 | # for summary 28 | if type(words) is unicode: 29 | words = words.encode("utf-8").split() 30 | # for searchh 31 | elif type(words) is list: 32 | words = [word+'\n' for word in words] 33 | for ch in words: 34 | for times, key_words in enumerate(key_word): 35 | # i claim the times to prevent print common words for 36 | # more than one time 37 | if key_words in ch.lower(): 38 | print colored(ch, key_word_color, attrs=['bold', 'underline']), 39 | break 40 | if times == len(key_word) - 1: 41 | print colored(ch, words_color), 42 | if ch.endswith('.'): 43 | print '\n' 44 | else: 45 | for ch in [words.encode("utf-8")]: 46 | if ch == '.': 47 | print "\n" 48 | else: 49 | print colored(ch, words_color), 50 | 51 | def summary(self, args): 52 | """::summary:: 53 | used to get summary of a word, raise errors when the word meets 54 | more than one wikipage 55 | example: 56 | summary apple """ 57 | text = '' 58 | if not args: 59 | raise AssertionError(colored("function summary needs at\ 60 | least one argument!", "red", attrs=["bold"])) 61 | else: 62 | try: 63 | text = wikipedia.summary(args) 64 | except wikipedia.DisambiguationError as error: 65 | # the search term may refers to mutiple choices 66 | errors = [option.encode("utf-8") for option in error.options] 67 | message = "\"{0}\" may refer to: \n{1}"\ 68 | .format(error.title, '\n'.join(errors)) 69 | raise AssertionError(colored(message, "red", attrs=["bold"])) 70 | 71 | if not text: 72 | message = 'Not found!!!' 73 | raise AssertionError(colored(message, "red", attrs=["bold"])) 74 | print self.w_print(text, "white", args, "green") 75 | 76 | def search(self, args): 77 | """::search:: 78 | used to search for a certain word. 79 | example: 80 | 1. search wikipedia -> return words refer to 'wikipedia' 81 | 2. search wiki pedia -> return words refer to 'wiki' & 'pedia' 82 | 3. search wiki pedia 10 -> return 10 of the results refer to 'wiki' 83 | & 'pedia' """ 84 | res, key_words = [], [] 85 | num = 0 86 | if len(args) < 1: 87 | raise AssertionError(colored("function search needs at least one argument!", 88 | "red", attrs=["bold"])) 89 | # there may be more than 2 arguments, for example: search wiki pedia 10 90 | elif len(args) >= 2: 91 | try: 92 | num = int(args[-1]) 93 | except ValueError: 94 | raise AssertionError("num should be a decimal number") 95 | res = wikipedia.search(args[0: len(args) - 1], results=num) 96 | key_words = args[0: len(args) - 1] 97 | else: 98 | res = wikipedia.search(args[0]) 99 | key_words = args[0] 100 | self.w_print(res, "white", key_words, "green") 101 | 102 | def random(self, args): 103 | """::random:: 104 | used to have a title even show its summary randomly. 105 | example: 106 | 1. random s(or summary) -> get summary of a random keyword 107 | 2. random -> get a random keyword""" 108 | if len(args) > 1: 109 | raise AssertionError(colored("function random has more than one argument!", 110 | "red", attrs=["bold"])) 111 | elif len(args) == 1 and (args[0] == "s" or args[0] == 'summary'): 112 | title = wikipedia.random().encode("utf-8") 113 | cprint(title, 'blue', attrs=['bold', 'dark']) 114 | try: 115 | self.summary(title) 116 | except wikipedia.DisambiguationError as error: 117 | error(u"\"{0}\" may refer to: \n{1}".format(error.title,\ 118 | '\n'.join(error.options))) 119 | else: 120 | title = wikipedia.random().encode("utf-8") 121 | try: 122 | cprint(title, 'blue', attrs=['bold', 'dark']) 123 | except UnicodeEncodeError: 124 | error(colored("Unicode encode failed!", "red", attrs=["bold"])) 125 | 126 | def geosearch(self, args): 127 | """::geosearch:: 128 | used to find out what happend at a certain location or 129 | in the range of radius. 130 | examole: 131 | 1. geosearch 180 27 -> return event take place at 180' 27' 132 | 2. geosearch 180 27 100 -> return event take place in 100 meters range from 133 | point 180' 27'""" 134 | global geosearch_res 135 | [latitude, longtitude, radius] = [0] * 3 136 | 137 | if len(args) < 2 or len(args) > 3: 138 | raise AssertionError(colored("function geosearch handle 2 or 3 arguments!",\ 139 | "red", attrs=["bold"])) 140 | elif len(args) == 2: 141 | [latitude, longtitude] = args[:] 142 | elif len(args) == 3: 143 | [latitude, longtitude, radius] = args[:] 144 | 145 | try: 146 | geosearch_res = wikipedia.geosearch(latitude, longtitude, radius=radius) 147 | except wikipedia.WikipediaException: 148 | raise AssertionError(colored("An unknown error occured: 'Invalid coordinate\ 149 | provided'. Please report it on GitHub!", "red", attrs=["bold"])) 150 | 151 | for res in geosearch_res: 152 | cprint(res + '\n', "green") 153 | 154 | def help(self, args): 155 | """::help:: 156 | instruction of wiki_terminal 157 | example: 158 | 1. help function -> how to use function 159 | 2. help -> all the instruction desplayed""" 160 | if len(args) == 0: 161 | for func in self.__all__: 162 | print getattr(self, func).__doc__ 163 | else: 164 | for func in args: 165 | print getattr(self, func).__doc__ 166 | -------------------------------------------------------------------------------- /wiki/wiki_lexer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from pygments.lexer import RegexLexer, words 4 | from pygments.token import * 5 | 6 | class WikiLexer(RegexLexer): 7 | """ 8 | Lexer for Structured Function Language. 9 | """ 10 | name = 'wiki' 11 | tokens = { 12 | 'root': [ 13 | (r'\s+', Text), 14 | (r'/\*', Comment.Multiline), 15 | (words(( 16 | 'SUMMARY', 'SEARCH', 'RANDOM', 17 | 'GEOSEARCH', 'QUIT', 'HELP', 18 | 'summary', 'search', 'random', 19 | 'geosearch', 'quit', 'help'), 20 | suffix=r'\b'), Keyword) 21 | ]} 22 | --------------------------------------------------------------------------------