Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added option to open stack overflow url directly, closes #191 #193

Merged
merged 8 commits into from
Jul 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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