Compare commits

...

5 Commits

Author SHA1 Message Date
Julien Palard 69c48d613c
Releasing 0.1.4. 2022-12-01 14:51:24 +01:00
Christophe Nanteuil 86263ffcba
print filename if multiple files parsed (#59) 2022-12-01 14:47:03 +01:00
Christophe Nanteuil b39636c907
Add blame option (#57) 2022-12-01 14:46:27 +01:00
Christophe Nanteuil f790dbb2f7
allow to specify several exclude-dir options (#55) 2022-12-01 14:44:23 +01:00
Julien Palard e08a750ef7
Releasing 0.1.3. 2022-08-30 17:21:50 +02:00
5 changed files with 121 additions and 58 deletions

View File

@ -13,15 +13,19 @@ and `pogrep` is a part of it! Go check out [Poutils](https://pypi.org/project/po
Print usage: `pogrep --help`
Find how 'flavors' has already been translated: search recursively in the
current directory, show the names of the matching files, excluding the venv
directory which contains a virtual env:
current directory, show the names of the matching files, excluding the venv and the
locales directories which are not relevant:
`pogrep --recursive --line-number --exclude-dir venv flavor `
`pogrep --recursive --line-number --exclude-dir venv --exclude-dir locales flavor `
Search the word 'typo' in traductions, but not in sources:
`pogrep --recursive --translation --no-source --word-regexp typo `
Blame usage of 'allogène' in traductions:
`pogrep --recursive --ignore-case --blame allogène `
## Contributing

View File

@ -1,7 +1,7 @@
"""Find translations examples by grepping in .po files.
"""
__version__ = "0.1.2"
__version__ = "0.1.4"
import argparse
import glob
@ -10,6 +10,7 @@ import sys
from textwrap import fill
from typing import Sequence, NamedTuple, List, Tuple, Optional
from shutil import get_terminal_size
from subprocess import run, CalledProcessError
import regex
import polib
@ -136,14 +137,12 @@ def find_in_po(
def display_results(
matches: Sequence[Match],
pattern: str,
line_number: bool,
files_with_matches: bool,
args: argparse.Namespace,
grep_colors: GrepColors,
):
"""Display matches as a colorfull table."""
files = {match.file for match in matches}
if files_with_matches: # Just print filenames
if args.files_with_matches: # Just print filenames
for file in files:
if grep_colors:
print(grep_colors.start("fn") + file + grep_colors.NO_COLOR)
@ -155,9 +154,9 @@ def display_results(
term_width = get_terminal_size()[0]
for match in matches:
left = match.msgid
if line_number:
if args.line_number:
pnum = str(match.line) + ":"
if len(files) > 1:
if args.print_filenames:
pfile = match.file + ":"
else:
pfile = ""
@ -172,7 +171,10 @@ def display_results(
if grep_colors:
print(
colorize(
tabulate(table, tablefmt="fancy_grid"), pattern, grep_colors, prefixes
tabulate(table, tablefmt="fancy_grid"),
args.pattern,
grep_colors,
prefixes,
)
)
else:
@ -273,6 +275,7 @@ def parse_args() -> argparse.Namespace:
)
parser.add_argument(
"--exclude-dir",
action="append",
help="Skip any command-line directory with a name suffix that matches "
"the pattern. "
"When searching recursively, skip any subdirectory whose base name "
@ -291,18 +294,57 @@ def parse_args() -> argparse.Namespace:
"environment variable GREP_COLORS. The deprecated environment variable "
"GREP_COLOR is still supported, but its setting does not have priority.",
)
parser.add_argument(
"--blame",
action="store_true",
help="Annotate each line from git information for the entries of each "
"match line. Implies --no-source and --translation.",
)
parser.add_argument("pattern")
parser.add_argument("path", nargs="*")
return parser.parse_args()
args = parser.parse_args()
if args.color == "auto":
args.color = sys.stdout.isatty()
else:
args.color = args.color != "never"
if args.fixed_strings:
args.pattern = regex.escape(args.pattern)
if args.word_regexp:
args.pattern = r"\b" + args.pattern + r"\b"
if args.ignore_case:
args.pattern = r"(?i)" + args.pattern
if args.blame:
args.no_source = True
args.translation = True
return args
def run_git(
lines_list: Sequence[int], filename: str, pattern: str, grep_colors: GrepColors
):
"""run git blame for the specified lines in filename
if grep_colors is not None then the pattern is highlighted
"""
cmd_line = ["git", "blame"]
cmd_line.extend(f"-L {line},/^$/" for line in lines_list)
cmd_line.append(filename)
try:
result = run(cmd_line, capture_output=True, text=True, check=True)
except CalledProcessError as exc:
print(exc.stderr, file=sys.stderr)
return
if grep_colors:
print(colorize(result.stdout, pattern, grep_colors))
else:
print(result.stdout)
def main():
"""Command line entry point."""
args = parse_args()
if args.color == "auto":
args.color = sys.stdout.isatty()
else:
args.color = args.color != "never"
if args.color:
grep_colors = GrepColors()
try:
@ -311,24 +353,34 @@ def main():
pass
else:
grep_colors = None
if args.fixed_strings:
args.pattern = regex.escape(args.pattern)
if args.word_regexp:
args.pattern = r"\b" + args.pattern + r"\b"
if args.ignore_case:
args.pattern = r"(?i)" + args.pattern
files = process_path(args.path, args.recursive)
args.print_filenames = len(files) > 1
if args.exclude_dir:
files = [f for f in files if args.exclude_dir.rstrip(os.sep) + os.sep not in f]
files = [
f
for f in files
if not any(excl.rstrip(os.sep) + os.sep in f for excl in args.exclude_dir)
]
errors, results = find_in_po(args.pattern, files, args.no_source, args.translation)
if not args.no_messages:
for error in errors:
print(error, file=sys.stderr)
if args.blame:
current_file = ""
lines_list = []
for res in results:
if res.file != current_file:
if current_file:
run_git(lines_list, current_file, args.pattern, grep_colors)
current_file = res.file
lines_list = []
lines_list.append(res.line)
if lines_list:
run_git(lines_list, current_file, args.pattern, grep_colors)
return
display_results(
results,
args.pattern,
args.line_number,
args.files_with_matches,
args,
grep_colors,
)

View File

@ -1,3 +1,41 @@
[build-system]
requires = ["setuptools", "wheel"]
requires = ["setuptools>=61.2"]
build-backend = "setuptools.build_meta"
[project]
name = "pogrep"
description = "Find translations examples by grepping in .po files."
authors = [{name = "Julien Palard", email = "julien@palard.fr"}]
license = {text = "MIT License"}
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
]
urls = {Homepage = "https://github.com/JulienPalard/pogrep"}
requires-python = ">= 3.6"
dependencies = [
"regex",
"polib",
"tabulate",
]
dynamic = ["version"]
[project.readme]
file = "README.md"
content-type = "text/markdown; charset=UTF-8"
[project.scripts]
pogrep = "pogrep:main"
[tool.setuptools]
py-modules = ["pogrep"]
include-package-data = false
[tool.setuptools.dynamic.version]
attr = "pogrep.__version__"

View File

@ -1,30 +0,0 @@
[metadata]
name = pogrep
version = 0.1.2
description = Find translations examples by grepping in .po files.
long_description = file: README.md
long_description_content_type = text/markdown; charset=UTF-8
author = Julien Palard
author_email = julien@palard.fr
url = https://github.com/JulienPalard/pogrep
license = MIT License
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
[options]
py_modules = pogrep
python_requires = >= 3.6
install_requires =
regex
polib
tabulate
[options.entry_points]
console_scripts = pogrep=pogrep:main

View File

@ -1 +0,0 @@
__import__("setuptools").setup()