Compare commits
5 Commits
5c7f2b7154
...
69c48d613c
Author | SHA1 | Date | |
---|---|---|---|
69c48d613c | |||
![]() |
86263ffcba | ||
![]() |
b39636c907 | ||
![]() |
f790dbb2f7 | ||
e08a750ef7 |
10
README.md
10
README.md
|
@ -13,15 +13,19 @@ and `pogrep` is a part of it! Go check out [Poutils](https://pypi.org/project/po
|
||||||
Print usage: `pogrep --help`
|
Print usage: `pogrep --help`
|
||||||
|
|
||||||
Find how 'flavors' has already been translated: search recursively in the
|
Find how 'flavors' has already been translated: search recursively in the
|
||||||
current directory, show the names of the matching files, excluding the venv
|
current directory, show the names of the matching files, excluding the venv and the
|
||||||
directory which contains a virtual env:
|
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:
|
Search the word 'typo' in traductions, but not in sources:
|
||||||
|
|
||||||
`pogrep --recursive --translation --no-source --word-regexp typo `
|
`pogrep --recursive --translation --no-source --word-regexp typo `
|
||||||
|
|
||||||
|
Blame usage of 'allogène' in traductions:
|
||||||
|
|
||||||
|
`pogrep --recursive --ignore-case --blame allogène `
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
98
pogrep.py
98
pogrep.py
|
@ -1,7 +1,7 @@
|
||||||
"""Find translations examples by grepping in .po files.
|
"""Find translations examples by grepping in .po files.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "0.1.2"
|
__version__ = "0.1.4"
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import glob
|
import glob
|
||||||
|
@ -10,6 +10,7 @@ import sys
|
||||||
from textwrap import fill
|
from textwrap import fill
|
||||||
from typing import Sequence, NamedTuple, List, Tuple, Optional
|
from typing import Sequence, NamedTuple, List, Tuple, Optional
|
||||||
from shutil import get_terminal_size
|
from shutil import get_terminal_size
|
||||||
|
from subprocess import run, CalledProcessError
|
||||||
|
|
||||||
import regex
|
import regex
|
||||||
import polib
|
import polib
|
||||||
|
@ -136,14 +137,12 @@ def find_in_po(
|
||||||
|
|
||||||
def display_results(
|
def display_results(
|
||||||
matches: Sequence[Match],
|
matches: Sequence[Match],
|
||||||
pattern: str,
|
args: argparse.Namespace,
|
||||||
line_number: bool,
|
|
||||||
files_with_matches: bool,
|
|
||||||
grep_colors: GrepColors,
|
grep_colors: GrepColors,
|
||||||
):
|
):
|
||||||
"""Display matches as a colorfull table."""
|
"""Display matches as a colorfull table."""
|
||||||
files = {match.file for match in matches}
|
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:
|
for file in files:
|
||||||
if grep_colors:
|
if grep_colors:
|
||||||
print(grep_colors.start("fn") + file + grep_colors.NO_COLOR)
|
print(grep_colors.start("fn") + file + grep_colors.NO_COLOR)
|
||||||
|
@ -155,9 +154,9 @@ def display_results(
|
||||||
term_width = get_terminal_size()[0]
|
term_width = get_terminal_size()[0]
|
||||||
for match in matches:
|
for match in matches:
|
||||||
left = match.msgid
|
left = match.msgid
|
||||||
if line_number:
|
if args.line_number:
|
||||||
pnum = str(match.line) + ":"
|
pnum = str(match.line) + ":"
|
||||||
if len(files) > 1:
|
if args.print_filenames:
|
||||||
pfile = match.file + ":"
|
pfile = match.file + ":"
|
||||||
else:
|
else:
|
||||||
pfile = ""
|
pfile = ""
|
||||||
|
@ -172,7 +171,10 @@ def display_results(
|
||||||
if grep_colors:
|
if grep_colors:
|
||||||
print(
|
print(
|
||||||
colorize(
|
colorize(
|
||||||
tabulate(table, tablefmt="fancy_grid"), pattern, grep_colors, prefixes
|
tabulate(table, tablefmt="fancy_grid"),
|
||||||
|
args.pattern,
|
||||||
|
grep_colors,
|
||||||
|
prefixes,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -273,6 +275,7 @@ def parse_args() -> argparse.Namespace:
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--exclude-dir",
|
"--exclude-dir",
|
||||||
|
action="append",
|
||||||
help="Skip any command-line directory with a name suffix that matches "
|
help="Skip any command-line directory with a name suffix that matches "
|
||||||
"the pattern. "
|
"the pattern. "
|
||||||
"When searching recursively, skip any subdirectory whose base name "
|
"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 "
|
"environment variable GREP_COLORS. The deprecated environment variable "
|
||||||
"GREP_COLOR is still supported, but its setting does not have priority.",
|
"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("pattern")
|
||||||
parser.add_argument("path", nargs="*")
|
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():
|
def main():
|
||||||
"""Command line entry point."""
|
"""Command line entry point."""
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
if args.color == "auto":
|
|
||||||
args.color = sys.stdout.isatty()
|
|
||||||
else:
|
|
||||||
args.color = args.color != "never"
|
|
||||||
if args.color:
|
if args.color:
|
||||||
grep_colors = GrepColors()
|
grep_colors = GrepColors()
|
||||||
try:
|
try:
|
||||||
|
@ -311,24 +353,34 @@ def main():
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
grep_colors = None
|
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)
|
files = process_path(args.path, args.recursive)
|
||||||
|
args.print_filenames = len(files) > 1
|
||||||
if args.exclude_dir:
|
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)
|
errors, results = find_in_po(args.pattern, files, args.no_source, args.translation)
|
||||||
if not args.no_messages:
|
if not args.no_messages:
|
||||||
for error in errors:
|
for error in errors:
|
||||||
print(error, file=sys.stderr)
|
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(
|
display_results(
|
||||||
results,
|
results,
|
||||||
args.pattern,
|
args,
|
||||||
args.line_number,
|
|
||||||
args.files_with_matches,
|
|
||||||
grep_colors,
|
grep_colors,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,41 @@
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools", "wheel"]
|
requires = ["setuptools>=61.2"]
|
||||||
build-backend = "setuptools.build_meta"
|
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__"
|
30
setup.cfg
30
setup.cfg
|
@ -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
|
|
Loading…
Reference in New Issue
Block a user