Skip to content

Commit

Permalink
Added option to open stack overflow url directly, closes #191 (#193)
Browse files Browse the repository at this point in the history
* Added option to open stack overflow url directly , as refered in issue#191

* Added tests , Made some bug fixes , Made all discussed changes

* Changed open_url to open-url

* Changed multiple things, added support for invalid url and passing all checks on my side

* Codacy checks passing

* Optimised and refactored code

* use generic Exception

* Improve messages printed to the user

Co-authored-by: Gautam krishna R <rgautamkrishna@gmail.com>
Co-authored-by: Hedy Li <hedyhyry@gmail.com>
  • Loading branch information
3 people committed Sep 7, 2020
1 parent 59ba668 commit 4131acb
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ build/
*.egg
venv
.eggs
socli/data.json
socli/data.json
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ If you can't find an answer for your question in Stack Overflow, **socli** allow
```sh
socli -n
```
##### Opening a url directly
If you have the url of the Stack Overflow post then you can pass it using `--open-url` or `-o`.
For example
``` socli --open-url https://stackoverflow.com/questions/20639180/explanation-of-how-nested-list-comprehension-works```
### Syntax:
**socli** has the following syntax
Expand All @@ -119,6 +124,8 @@ Usage: socli [ Arguments] < Search Query >
| -d | --del | Deletes the configuration file generated by socli -u manually. | **socli -d** |
| -s | --sosearch | SoCLI uses Google search by default to search for questions. To override this and use stackoverflow's default search instead. | **socli -s -q for loop python** |
| -h | --help | Displays the help text. | **socli --help** |
| -o | --open-url | Displays the given url in socli if possible if not opens in browser. | **socli -o https://stackoverflow.com/questions/20639180/explanation-of-how-nested-list-comprehension-works** |
###### Query
This term refers to what you're searching for in Stack Overflow.
Expand Down
1 change: 1 addition & 0 deletions socli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def parse_arguments(command):
"its most voted answer. \n eg:- socli --res 2 --query "
"foo bar: Displays the second search result of the query"
" \"foo bar\"'s most voted answer")
parser.add_argument('--open-url' , '-o' , nargs=1 , type=str , help='To load the given url')
namespace = parser.parse_args(command)
return namespace

6 changes: 4 additions & 2 deletions socli/printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ def helpman():
" " + bold("--api or -a") + \
" : Sets a custom API key for socli" + '\n' + \
" " + bold("--sosearch or -s") + \
" : SoCLI uses google search by default. Use this option to search Stack Overflow directly."
" : SoCLI uses google search by default. Use this option to search Stack Overflow directly." + '\n' \
" " + bold("--open-url or -o") + \
" : Opens the given url in socli " + '\n'

help_text = make_header("\n\n< Search Query >:") + '\n' + \
"\nQuery to search on Stack Overflow" + '\n' + \
Expand Down Expand Up @@ -214,4 +216,4 @@ def display_results(url):
question_title, question_desc, question_stats, answers = search.get_question_stats_and_answer(url)
tui.question_post = tui.QuestionPage((answers, question_title, question_desc, question_stats, url))
tui.MAIN_LOOP = tui.EditedMainLoop(tui.question_post, palette)
tui.MAIN_LOOP.run()
tui.MAIN_LOOP.run()
48 changes: 47 additions & 1 deletion socli/socli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""

import os
import re
import sys
import logging
import requests
Expand Down Expand Up @@ -361,7 +362,51 @@ def main():
search.google_search = False
tag = namespace.tag
has_tags() # Adds tags to StackOverflow url (when not using google search.

if namespace.open_url:
import webbrowser
open_in_browser=False
display_condition=True
url_to_use=namespace.open_url[0]
if re.findall(r"^https:\/\/",url_to_use) !=[]:
pass
else:
url_to_use="https://" + url_to_use
try:
if url_to_use == "https://stackoverflow.com/questions/":
raise Exception('URL Error')
if url_to_use == "https://www.stackoverflow.com/questions/":
raise Exception('URL Error')
requests.get(url_to_use)
except Exception:
printer.print_warning("Error, could be:\n- invalid url\n- url cannot be opened in socli\n- internet connection error")
sys.exit(0)
nostackoverflow=re.findall(r"stackoverflow\.com",url_to_use)
if nostackoverflow == []:
open_in_browser=True
display_condition=False
printer.print_warning("Your url is not a stack overflow url.\nOpening in your browser...")
tag_matcher=re.findall(r"\/tag.+\/",url_to_use)
blog_matcher=re.findall(r"blog",url_to_use)
if tag_matcher != []:
extracted_tag=""
if re.findall(r"tagged",url_to_use) == []:
extracted_tag=re.split(r"\/",url_to_use)[4]
else:
extracted_tag=re.split(r"\/",url_to_use)[5]
open_in_browser=False
display_condition=False
tag=extracted_tag
search.socli_interactive(tag)
if blog_matcher != []:
open_in_browser=True
display_condition=False
printer.print_warning("Your url belongs to blog")
printer.print_warning("Opening in browser...")
if display_condition:
open_in_browser=False
display_results(url_to_use)
if open_in_browser:
webbrowser.open(url_to_use)
if namespace.res is not None: # If --res flag is present
# Automatically displays the result specified by the number
question_number = namespace.res
Expand Down Expand Up @@ -396,5 +441,6 @@ def main():
printer.helpman()



if __name__ == '__main__':
main()
20 changes: 20 additions & 0 deletions socli/tests/test_socli.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def test01_socliParse(self):
self.assertFalse(namespace.sosearch)
self.assertFalse(namespace.tag)
self.assertFalse(namespace.user)
self.assertTrue(not namespace.open_url)

def test02_socliParse(self):
command = "-h".split()
Expand All @@ -61,6 +62,7 @@ def test02_socliParse(self):
self.assertFalse(namespace.sosearch)
self.assertFalse(namespace.tag)
self.assertFalse(namespace.user)
self.assertTrue(not namespace.open_url)

def test03_socliParse(self):
command = "-iq python for loop".split()
Expand All @@ -78,6 +80,7 @@ def test03_socliParse(self):
self.assertFalse(namespace.sosearch)
self.assertFalse(namespace.tag)
self.assertFalse(namespace.user)
self.assertTrue(not namespace.open_url)

def test04_userJSON(self):
try:
Expand Down Expand Up @@ -118,6 +121,23 @@ def test07_searchStats(self):
except Exception:
raise SoCLITestingException("Search SO stats test failed.")

def test08_socliParse(self):
command = "--open-url https://stackoverflow.com/questions/20639180/explanation-of-how-nested-list-comprehension-works ".split()
namespace = _socli.parse_arguments(command)

self.assertFalse(namespace.api)
self.assertTrue(namespace.browse == [])
self.assertFalse(namespace.debug)
self.assertFalse(namespace.delete)
self.assertFalse(namespace.help)
self.assertFalse(namespace.interactive)
self.assertFalse(namespace.new)
self.assertTrue(namespace.query == [])
self.assertFalse(namespace.res)
self.assertFalse(namespace.sosearch)
self.assertFalse(namespace.tag)
self.assertFalse(namespace.user)
self.assertTrue(namespace.open_url!=[])

class SoCLITestingException(Exception):

Expand Down

0 comments on commit 4131acb

Please sign in to comment.