Skip to content

Commit

Permalink
version 0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
queirozfcom committed Apr 24, 2022
1 parent 461b90a commit d388a09
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 105 deletions.
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
jekyll-utils
=======

**TODO:**
- Add this to PyPa (tutorial here: [Package a Python Project and make it available on PyPa](https://queirozf.com/entries/package-a-python-project-and-make-it-available-via-pip-install-simple-example))
- Add tests for public functions

A small Python 3 command-line application (based upon [click](http://click.pocoo.org/6/)) to speed up some common tasks for those who blog using Jekyll.

This will be **especially** useful for people who post many short blog entries, as opposed to those who prefer to blog less frequently, with longer posts.
Expand All @@ -9,18 +13,20 @@ This will be **especially** useful for people who post many short blog entries,

- Prerequisites: `virtualenv`

- On Ubuntu, install it via `$ sudo apt-get install python3-virtualenv`
- On Ubuntu, install it via `$ sudo apt-get install python3-virtualenv`

- Installing jekyll-utils using pip
- Installing jekyll-utils from Github using pip

- `$ git clone https://github.com/queirozfcom/jekyll-utils`
- `$ cd jekyll-utils`
- `$ virtualenv -p python3 jekyll-venv`
- `$ source jekyll-venv/bin/activate`
- `$ pip install .`
- `$ git clone https://github.com/queirozfcom/jekyll-utils`
- `$ cd jekyll-utils`
- `$ virtualenv -p python3 jekyll-venv`
- `$ source jekyll-venv/bin/activate`
- `$ pip install .`

This will install all commands to your virtualenv. Type `jk-` and then hit `<TAB>` to see all available commands.

![jekyll-utils-commands](https://i.imgur.com/f1sF6Iq.gif)

- Initial configs. These are needed to start using the tools:

- `$ jk-config-set-editor <your editor name>`
Expand Down
17 changes: 8 additions & 9 deletions jekyllutils/configs.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import click

from jekyllutils.helpers import files, configs
from jekyllutils.helpers.messages import wrap_success
from jekyllutils.helpers import configs
from jekyllutils import files
from jekyllutils.helpers.colours import with_success_prefix


@click.command()
@click.argument('path')
def set_path_to_posts_dir(path):
def set_posts_path(path):
absolute_path = files.resolve_path(path)
configs.set_path_to_posts_dir(absolute_path)
click.echo(wrap_success(
"""Config key "path-to-jekyll-posts" was set to "{0}" """.format(path)))
configs.set_posts_path_dir(absolute_path)
click.echo(with_success_prefix(f"""Config key "posts-path" was set to "{path}" """))


@click.command()
@click.argument('name')
def set_editor(name):
configs.set_editor_name(name)
click.echo(
wrap_success("""Config key "editor" was set to "{0}" """.format(name)))
click.echo(with_success_prefix(f"""Config key "editor" was set to "{name}" """))


@click.command()
Expand All @@ -29,4 +28,4 @@ def dump_configs():
@click.command()
def clear_configs():
configs.clear_configs()
click.echo(wrap_success("Configs cleared"))
click.echo(with_success_prefix("Configs cleared"))
69 changes: 25 additions & 44 deletions jekyllutils/helpers/files.py → jekyllutils/files.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import os
import re
from pathlib import Path

import os
from jekyllutils.helpers.colours import wrap_yellow, wrap_blue, wrap_green
from jekyllutils.helpers.text import match_all, filter_match_all


def resolve_path(path, strip_trailing_slash=True):
Expand Down Expand Up @@ -28,7 +31,7 @@ def list_files(absolute_directory, keywords):
matches = []

for root, dirnames, filenames in os.walk(absolute_directory):
for filename in _filter_match_all(filenames, keywords):
for filename in filter_match_all(filenames, keywords):
matches.append(os.path.join(root, filename))

# remove the paths, return only file names
Expand Down Expand Up @@ -56,7 +59,7 @@ def list_filenames_by_tag(absolute_directory, tags):
with open(absolute_path_to_file, "r") as f:
for line in f:
if line.strip().startswith("tags:"):
if _match_all(line, tags):
if match_all(line, tags):
matches.append(filename)
break

Expand All @@ -69,7 +72,7 @@ def list_unpublished_filenames(absolute_directory, include_wip):
(i.e. files where published: false in front-matter)
:param absolute_directory:
:param include_wip: if true, also return files that contain "wip alert"
:param include_wip: if true, also return files that contain "wip alert" and "TODO"
:return: a list of the filenames
"""
matches = []
Expand All @@ -79,47 +82,25 @@ def list_unpublished_filenames(absolute_directory, include_wip):
absolute_path_to_file = os.path.join(root, filename)

with open(absolute_path_to_file, "r") as f:
for line in f:
if line.strip().startswith("published:"):
if _match_all(line, ("false",)):
matches.append("[UNP]" + filename)
break
if include_wip and ("wip alert" in line.lower()):
matches.append("[WIP]" + filename)
break

return matches


def _match_all(s, keywords):
"""
True if all strings in keywords are contained in s, False otherwise.
Case-insensitive.
:param s: string
:param keywords: a tuple containing keywords that should all be included
:return: True if all strings in keywords are contained in s, False otherwise
"""

for kw in keywords:
if kw.lower().strip() not in s.lower().strip():
return False

return True


def _filter_match_all(elements, keywords):
"""
Returns the elements for which all keywords are contained.
for line in f:

:param elements: a list of strings to filter
:param keywords: a tuple containing keywords that should all be included
:return: matching matching elements
"""
matching = []
line_clean = line.strip().lower()

for elem in elements:
if all(keyword in elem for keyword in keywords):
matching.append(elem)
if line_clean.startswith("published:") and match_all(line_clean, ("false",)):
prefix = wrap_yellow("[UNP] ")
matches.append(f"{prefix} {filename}")
break
elif include_wip and ("wip alert" in line_clean):
prefix = wrap_blue("[WIP] ")
matches.append(f"{prefix} {filename}")
break
elif include_wip and (re.search("todo: ", line_clean) or
re.search("todo\n", line_clean) or
re.search("^todo ", line_clean) or
re.search(" todo ", line_clean)):
prefix = wrap_green("[TODO]")
matches.append(f"{prefix} {filename}")
break

return matching
return list(set(matches))
23 changes: 13 additions & 10 deletions jekyllutils/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from subprocess import call

import click
from jekyllutils.helpers.configs import get_path_to_posts_dir, get_editor_name
from jekyllutils.helpers.configs import get_posts_path, get_editor_name
from jekyllutils.helpers.editors import get_executable_from_name
from jekyllutils.helpers.messages import wrap_success
from jekyllutils.helpers.colours import with_success_prefix
from slugify import slugify


Expand All @@ -33,7 +33,7 @@ def new_post(title, tag, image):

file_name = date.strftime("%Y-%m-%d") + "-" + slug + ".markdown"

path_to_file = get_path_to_posts_dir().rstrip("/") + "/" + file_name
path_to_file = get_posts_path().rstrip("/") + "/" + file_name

with open(path_to_file, "w") as f:
f.write(textwrap
Expand All @@ -46,7 +46,7 @@ def new_post(title, tag, image):
call([editor_executable, path_to_file])
time.sleep(2) # just to give the os time for the editor to load

click.echo(wrap_success("Post created at: {0}".format(path_to_file)))
click.echo(with_success_prefix("Post created at: {0}".format(path_to_file)))


@click.command()
Expand All @@ -60,7 +60,7 @@ def new_post_paper_summary(title, tag):

contents = _get_contents_paper_summary()

title_full = "Paper Summary: "+title
title_full = "Paper Summary: " + title

slug = slugify(title_full)
date = datetime.now()
Expand All @@ -69,7 +69,7 @@ def new_post_paper_summary(title, tag):

file_name = date.strftime("%Y-%m-%d") + "-" + slug + ".markdown"

path_to_file = get_path_to_posts_dir().rstrip("/") + "/" + file_name
path_to_file = get_posts_path().rstrip("/") + "/" + file_name

with open(path_to_file, "w") as f:
f.write(textwrap
Expand All @@ -82,7 +82,8 @@ def new_post_paper_summary(title, tag):
call([editor_executable, path_to_file])
time.sleep(2) # just to give the os time for the editor to load

click.echo(wrap_success("Post (Paper Summary) created at: {0}".format(path_to_file)))
click.echo(with_success_prefix("Post (Paper Summary) created at: {0}".format(path_to_file)))


@click.command()
@click.option('--tag', '-t', multiple=True, help="Multiple values allowed")
Expand All @@ -95,7 +96,7 @@ def new_post_crypto_asset_overview(title, tag):

contents = _get_contents_crypto_asset_overview()

title_full = "Crypto Asset Overview: "+title
title_full = "Crypto Asset Overview: " + title

slug = slugify(title_full)
date = datetime.now()
Expand All @@ -104,7 +105,7 @@ def new_post_crypto_asset_overview(title, tag):

file_name = date.strftime("%Y-%m-%d") + "-" + slug + ".markdown"

path_to_file = get_path_to_posts_dir().rstrip("/") + "/" + file_name
path_to_file = get_posts_path().rstrip("/") + "/" + file_name

with open(path_to_file, "w") as f:
f.write(textwrap
Expand All @@ -117,7 +118,8 @@ def new_post_crypto_asset_overview(title, tag):
call([editor_executable, path_to_file])
time.sleep(2) # just to give the os time for the editor to load

click.echo(wrap_success("Post (Paper Summary) created at: {0}".format(path_to_file)))
click.echo(with_success_prefix("Post (Paper Summary) created at: {0}".format(path_to_file)))


def _get_contents_no_img():
return """
Expand Down Expand Up @@ -158,6 +160,7 @@ def _get_contents_img():
"""


def _get_contents_paper_summary():
return """
---
Expand Down
18 changes: 18 additions & 0 deletions jekyllutils/helpers/colours.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
def with_error_prefix(msg):
return f"\033[31mERROR: \033[00m{msg}"


def with_success_prefix(msg):
return f"\033[32mSUCCESS: \033[00m{msg}"


def wrap_yellow(msg):
return f"\033[33m{msg}\033[00m"


def wrap_green(msg):
return f"\033[32m{msg}\033[00m"


def wrap_blue(msg):
return f"\033[34m{msg}\033[00m"
36 changes: 24 additions & 12 deletions jekyllutils/helpers/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import os
import toml
from appdirs import user_config_dir
from jekyllutils.helpers.messages import wrap_error
from jekyllutils.helpers.colours import with_error_prefix, wrap_yellow, with_success_prefix


def get_path_to_posts_dir():
return _get_config("path-to-jekyll-posts")
def get_posts_path():
return _get_config("posts-path")


def get_editor_name():
Expand Down Expand Up @@ -37,35 +37,46 @@ def set_editor_name(name):
_set_config("editor", name)


def set_path_to_posts_dir(path):
_set_config("path-to-jekyll-posts", path)
def set_posts_path_dir(path):
_set_config("posts-path", path)


# private

def _set_config(name, value):
with open(_get_config_file(), "r+") as f:
_create_config_file_if_needed()

with open(_get_path_to_config_file(), "a+") as f:

# move the pointer to the start because we want to read the file first
f.seek(0)
config = toml.loads(f.read())
config[name] = value
new_conf = toml.dumps(config)

# then delete everything and write the new config
f.truncate(0)
f.seek(0)
f.write(new_conf)



def _get_config(name):
try:
with open(_get_config_file()) as f:
with open(_get_path_to_config_file()) as f:
config = toml.loads(f.read())
return config[name]
except KeyError as e:
print(wrap_error(
"""Please set a value for key "{0}" in the config.""".format(name)))

sample_command = f"jk-config-set-{name} foo-bar"

print(with_error_prefix(
f"""Please set a value for key "{name}" in the config.\nFor example: {wrap_yellow(sample_command)}"""))
sys.exit(1)


def _create_config_file_if_needed():
filename = _get_config_file()
filename = _get_path_to_config_file()

if os.path.isfile(filename):
return
Expand All @@ -78,13 +89,14 @@ def _create_config_file_if_needed():
raise

with open(filename, "w") as f:
print(with_success_prefix(f"Created new config file at: {filename}"))
f.write("")


def _get_config_file():
def _get_path_to_config_file():
return user_config_dir("jekyll-utils", "queirozfcom") + "/config.toml"


def _raise_error_if_no_config():
if not os.path.isfile(_get_config_file()):
if not os.path.isfile(_get_path_to_config_file()):
raise FileNotFoundError("Config file not found")
6 changes: 0 additions & 6 deletions jekyllutils/helpers/messages.py

This file was deleted.

Loading

0 comments on commit d388a09

Please sign in to comment.