Skip to content
Open
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Change Log
==========

Version 2.1.0+Win10 *(2019-03-05)*
----------------------------

* New: Colors on Windows 10 thanks to [Windows 10 VT100 support](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences)
* New: `-o` / `--output` flag to [tee](https://en.wikipedia.org/wiki/tee_(command)) output to a file while simultaneously displaying it in the console.
* New: `-n` / `--no-color` flag to disable colors altogether.

Version 2.1.0 *(2016-09-07)*
----------------------------

Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PID Cat
PID Cat with [Windows 10 VT100 support](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences)
=======

An update to Jeff Sharkey's excellent [logcat color script][1] which only shows
Expand All @@ -25,6 +25,9 @@ Install

Get the script:

* Windows: Download `pidcat.py` and `pidcat.cmd` and place them on your PATH.
Make sure you also have Python installed with `python.exe` on PATH.

* OS X: Use [Homebrew][2].

brew install pidcat
Expand All @@ -43,13 +46,15 @@ Make sure that `adb` from the [Android SDK][3] is on your PATH. This script will
not work unless this is that case. That means, when you type `adb` and press
enter into your terminal something actually happens.

To include `adb` and other android tools on your path:
To include `adb` and other android tools on your path on OS X / Linux:

export PATH=$PATH:<path to Android SDK>/platform-tools
export PATH=$PATH:<path to Android SDK>/tools

Include these lines in your `.bashrc` or `.zshrc`.

On Widnows add `<path to Android SDK>/platform-tools` and `<path to Android SDK>/tools` to your PATH in [System Properties](https://support.microsoft.com/en-sg/help/310519/how-to-manage-environment-variables-in-windows-xp)

*Note:* `<path to Android SDK>` should be absolute and not relative.

[1]: http://jsharkey.org/blog/2009/04/22/modifying-the-android-logcat-stream-for-full-color-debugging/
Expand Down
1 change: 1 addition & 0 deletions pidcat.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@python.exe "%~dp0\pidcat.py" %*
57 changes: 53 additions & 4 deletions pidcat.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@
import re
import subprocess
from subprocess import PIPE
from ctypes import *
from platform import win32_ver

__version__ = '2.1.0'
__version__ = '2.1.0+Win10'

win_ver = win32_ver()[0]
show_colors = (win_ver == '10' or win_ver == '') and sys.stdout.isatty()

LOG_LEVELS = 'VDIWEF'
LOG_LEVELS_MAP = dict([(LOG_LEVELS[i], i) for i in range(len(LOG_LEVELS))])
Expand All @@ -46,12 +51,44 @@
parser.add_argument('-i', '--ignore-tag', dest='ignored_tag', action='append', help='Filter output by ignoring specified tag(s)')
parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + __version__, help='Print the version number and exit')
parser.add_argument('-a', '--all', dest='all', action='store_true', default=False, help='Print all log messages')
parser.add_argument('-o', '--output', dest='output', type=str, default='', help='Output filename')
parser.add_argument('-n', '--no-color', dest='no_color', action='store_true', help='Disable colors')
parser.add_argument('-r', '--regex', dest='regex', type=str, help='Print only when matches REGEX and REGEX is regular expression logcat -e REGEX')

args = parser.parse_args()
min_level = LOG_LEVELS_MAP[args.min_level.upper()]

if (args.no_color):
show_colors = False

package = args.package


# enabling Windows 10 VT100 support
def enableVT100():
STD_OUTPUT_HANDLE = -11
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4

stdout = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
if stdout == -1:
raise WinError()

mode = c_uint()
if windll.kernel32.GetConsoleMode(stdout, byref(mode)) == 0:
raise WinError()

mode.value = mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING

if windll.kernel32.SetConsoleMode(stdout, mode) == 0:
raise WinError()

if (show_colors):
enableVT100()

output_file = False
if (args.output):
output_file = open(args.output, 'a+')

base_adb_command = ['adb']
if args.device_serial:
base_adb_command.extend(['-s', args.device_serial])
Expand Down Expand Up @@ -139,6 +176,13 @@ def allocate_color(tag):
LAST_USED.append(color)
return color

NO_COLOR = re.compile(r'\033\[.*?m')

def output(line):
line_nocolor = '' if show_colors and not output_file else NO_COLOR.sub('', line)
print(line if show_colors else line_nocolor)
if (output_file):
output_file.write(line_nocolor + '\n')

RULES = {
# StrictMode policy violation; ~duration=319 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=31 violation=1
Expand Down Expand Up @@ -178,6 +222,8 @@ def allocate_color(tag):
adb_command = base_adb_command[:]
adb_command.append('logcat')
adb_command.extend(['-v', 'brief'])
if args.regex:
adb_command.extend(['-e',args.regex])

# Clear log before starting logcat
if args.clear_logcat:
Expand Down Expand Up @@ -302,7 +348,7 @@ def tag_in_tags_regex(tag, tags):
linebuf += colorize(' ' * (header_size - 1), bg=WHITE)
linebuf += ' PID: %s UID: %s GIDs: %s' % (line_pid, line_uid, line_gids)
linebuf += '\n'
print(linebuf)
output(linebuf)
last_tag = None # Ensure next log gets a tag printed

dead_pid, dead_pname = parse_death(tag, message)
Expand All @@ -312,7 +358,7 @@ def tag_in_tags_regex(tag, tags):
linebuf += colorize(' ' * (header_size - 1), bg=RED)
linebuf += ' Process %s (PID: %s) ended' % (dead_pname, dead_pid)
linebuf += '\n'
print(linebuf)
output(linebuf)
last_tag = None # Ensure next log gets a tag printed

# Make sure the backtrace is printed after a native crash
Expand Down Expand Up @@ -357,4 +403,7 @@ def tag_in_tags_regex(tag, tags):
message = matcher.sub(replace, message)

linebuf += indent_wrap(message)
print(linebuf.encode('utf-8'))
output(linebuf.encode('utf-8'))

if (output_file):
output_file.close()