Giter Site home page Giter Site logo

Comments (23)

sbwilson avatar sbwilson commented on August 23, 2024 5

I wonder whether the console view's base class has changed. I spent a little time playing with this tonight, and can't get the new console to trigger the method [NSTextStorage fixAttributesInRange:]. From digging through the class-dump'ed source for a variety of the frameworks. The most obvious (found in IDEKit.framework) is this:

IDEConsoleTextView * consoleTextView = [[[[[[[NSApplication sharedApplication] _workspaceWindowControllers] firstObject] editorArea] valueForKey: @"_activeDebuggerArea"] consoleArea] valueForKey: @"_consoleView"]

I've played a little with setting breakpoints and trying to inject the xc_fixAttributesInRange: method into this class, and neither seems to have any success. Further, printing the contents of this view suggests it's empty.

There's a second ivar of the consoleArea (of type IDEConsoleArea), _consoleViewSwift, which returns a Swift class IDEConsoleEditorView (found in PlugIns/IDESourceEditor.framework). Printing the -string method of this class into the console gives the correct output. It's full path is given as:

[[[[[[[[NSApplication sharedApplication] _workspaceWindowControllers] firstObject] editorArea] valueForKey: @"_activeDebuggerArea"] valueForKey: @"_rightReplacementView"] valueForKey: @"_installedViewController"] valueForKey: @"_consoleViewSwift"]

And we can confirm that this the new console view:

po [[[[[[[[[[[NSApplication sharedApplication] _workspaceWindowControllers] firstObject] editorArea] valueForKey: @"_activeDebuggerArea"] valueForKey: @"_rightReplacementView"] subviews] firstObject] subviews] firstObject] subviews]
<__NSArrayM 0x608001049e40>(
<DVTScopeBarView: 0x12410adf0>,
IDEConsoleEditorView: Frame: (0.0, 28.0, 967.0, 389.0), Bounds: (0.0, 0.0, 967.0, 389.0) contentViewOffset: 0.0
)

So I suspect this is the starting point for the Xcode 10 version of this implementation. My attempts to go any further here are hampered by my lack of Swift experience, such as an inability to access the ivars of the IDESourceEditorView. I'll keep hacking tonight, but I don't suspect I'll get much further...

Edit:
It may actually be worth looking at the swift class SourceEditorLineLayer inside SourceEditor.framework. It's a CALayer-based class, and it looks like the -contents of these are CGImages. I suspect the -renderInContext: method generates these images, so maybe swizzling this method could be ticket to a solution?

from xcodecolors.

basvankuijck avatar basvankuijck commented on August 23, 2024

No, no luck whatsoever. usigning Xcode and adding the uuid in the plugin worked on Xcode9.
But Xcode10 (the GM at least) is not working as I was hoping it would.

from xcodecolors.

sunnyyoung avatar sunnyyoung commented on August 23, 2024

Yes, the same issue here, with unsigned Xcode 10 Release version. πŸ’”

from xcodecolors.

tanranran avatar tanranran commented on August 23, 2024

me too Xcode Version 10.0 (10A255)

from xcodecolors.

absolutlabs avatar absolutlabs commented on August 23, 2024

actually it's still working in the Report navigator > debug session , but less useful than directly in the console :/

from xcodecolors.

basvankuijck avatar basvankuijck commented on August 23, 2024

Can someone confirm that other plugins still work and it's just this one.
Or that Apple has actually closed the door completely on xcplugin.

from xcodecolors.

gklka avatar gklka commented on August 23, 2024

I think they work fine (including this one), only the console has been changed, and XcodeColors cannot patch it the old way.

from xcodecolors.

absolutlabs avatar absolutlabs commented on August 23, 2024

yep, exactly

from xcodecolors.

sbwilson avatar sbwilson commented on August 23, 2024

I think they work fine (including this one), only the console has been changed, and XcodeColors cannot patch it the old way.

Except it also looks like the editor view has been rewritten in Swift as well β€” perusing the view hierarchy shows that there's now a IDESourceEditor.SourceCodeEditorContainerView_ControlledBy_IDESourceEditor.SourceCodeEditor view, which could mean that many other plugins are likely to be affected...

from xcodecolors.

basvankuijck avatar basvankuijck commented on August 23, 2024

I made a dump of the view hierarchy of Xcode10: https://gist.github.com/basvankuijck/32693fd517c641f94c13295344f9620e

from xcodecolors.

sbwilson avatar sbwilson commented on August 23, 2024

I've had a little more of a dig, now that I have figured out how to set breakpoints on these system Swift classes (b SourceEditor.SourceEditorLineLayer.init was my first success)...

The line layers are created by SourceEditorLayoutManager.makeLineLayerForLine(..). Early in the disassembly, it calls SourceEditor.SourceEditorLayoutManager.attributedStringAndImagesForLine(..).
If we were able to swizzle this method, first calling the original method, followed by most of the meat from ApplyANSIColors(), would we get back our beloved colours?

from xcodecolors.

sbwilson avatar sbwilson commented on August 23, 2024

Some further exploration. My class-dump'ed version of SourceEditor doesn't include any methods inside the SourceEditorLayoutManager class β€” though I'd wager that it may be due to the fact that this method returns a tuple instead of a single value, and hence class-dump can't interpret it properly. But I can find the IMP for this method:

(lldb) b SourceEditor.SourceEditorLayoutManager.attributedStringAndImagesForLine
Breakpoint 2: where = SourceEditor`SourceEditor.SourceEditorLayoutManager.attributedStringAndImagesForLine(_: Swift.Int, context: SourceEditor.SourceEditorTextAttributeContext) -> (__C.NSAttributedString, Swift.Array<(image: __C.CGImageRef, columnRange: Swift.Range<Swift.Int>)>), address = 0x0000000119a94f70

That address can be cast to an IMP and displayed:

(lldb) po (IMP)0x0000000119a94f70
(SourceEditor`SourceEditor.SourceEditorLayoutManager.attributedStringAndImagesForLine(_: Swift.Int, context: SourceEditor.SourceEditorTextAttributeContext) -> (__C.NSAttributedString, Swift.Array<(image: __C.CGImageRef, columnRange: Swift.Range<Swift.Int>)>))

I'm not certain we can necessarily work backwards from here though, nor how to go about swizzling this method. So I think I'll pause here, remove my XcodeColor bits from my current logger for now, and hopefully somebody Swiftier than I will be able to take this from here...

from xcodecolors.

basvankuijck avatar basvankuijck commented on August 23, 2024

For those concerning, here is a class dump of SourceEditor for Xcode10: https://github.com/basvankuijck/Xcode-headers/tree/master/SourceEditor

from xcodecolors.

mooch443 avatar mooch443 commented on August 23, 2024

I'm afraid I can't offer much help with this (other than emotional support), but I don't want to live without my colors... It's so puzzling that they wouldn't just add this as a feature. Seems like I need to learn Swift after all? Please do tell if anyone solves this first.

from xcodecolors.

sedwo avatar sedwo commented on August 23, 2024

@sbwilson @basvankuijck Your investigations in trying to get plugins working is very hopeful. I (and perhaps others) might even be inclined to support your efforts by tipping a patreon account. As this type of visual logging is still far superior then anything Apple has delivered.
I'd say keep up the great work to revive Xcode plugins!

from xcodecolors.

sbwilson avatar sbwilson commented on August 23, 2024

You need to stop saying all these encouraging words β€” I spent another few hours playing this morning when I shouldn't have...

The one success I can report is that one can add methods to SourceEditorLayoutManager using class_addMethod, and they can be called from both objc and Swift:

void myMethodIMP(id self, SEL _cmd)
{
	NSLog( @"calling -stupid" );
}

@implementation XcodeColors

+ (void)load
{
    ...
    Class cl = NSClassFromString( @"SourceEditor.SourceEditorLayoutManager" );
    class_addMethod( cl, @selector(stupid), (IMP) myMethodIMP,  "V@:" )
}

At my trusty breakpoint (attributedStringAndImagesForLine), I can call e [$r13 stupid] (where $r13 is the register for self β€” try register read to see them all, including the IMP) and I get the correct response -- the log message. Through some gymnastics, we can do the same within swift:

(lldb) p/x $r13 
(unsigned long) $21 = 0x0000000126719b30
(lldb) e -l swift -- (unsafeBitCast(0x0000000126719b30, to: AnyObject.self)).perform(Selector("stupid"))
2018-09-26 12:38:03.370609+1000 Xcode[27812:11154274] calling -stupid
(Unmanaged<AnyObject>?) $R22 = nil

It is possible to access some of the ivars from this class though, both in the debugger as well as the objc runtime methods, though there doesn't seem to be any interesting things there.

Has this achieved anything though? I doubt it. In order to do the swizzle, we need to get some handle to the method. From my explorations, it seems that a method must be tagged with @objc in order to use swizzling. I don't think that occurred, especially from looking at the output of class-dump for SourceEditorLayoutManager (see @basvankuijck's link above). Perhaps there's some hidden gems in the Swift runtime that we can leverage, but it doesn't look promising.

:(

from xcodecolors.

sandychales avatar sandychales commented on August 23, 2024

Excuse me, am I the only one who can't use this plugin in Xcode 9.2 after trying all suggestted method? I added DVTPlugInCompatibilityUUIDs, but it still not work.

from xcodecolors.

gklka avatar gklka commented on August 23, 2024

No, it does not work anymore.

from xcodecolors.

hahaGitHub avatar hahaGitHub commented on August 23, 2024

the same issue. I use xcode10.1 and the plugin still does not work.

from xcodecolors.

rakeyang avatar rakeyang commented on August 23, 2024

How to fix it?

from xcodecolors.

sedwo avatar sedwo commented on August 23, 2024

I think this plug-in is done. :/
Unless Apple opens up Xcode console manipulation.

from xcodecolors.

rakeyang avatar rakeyang commented on August 23, 2024

I think this plug-in is done. :/
Unless Apple opens up Xcode console manipulation.

Hope so.

from xcodecolors.

dbquarrel avatar dbquarrel commented on August 23, 2024

I didn't want to implement or change to another framework for logging, and I wanted the color functionality that is now long dead. I'm tired of apple deprecating things to death and frameworks that implement Swift breaking with every XCode release... so I wanted something just very simple and usable that would never break.

I implemented something using the bones of Xcode logger but not using any Xcode plugin. It is pretty simple to use this, all you need to do is call the logging functions and it will dump ANSI coded log output to /tmp/xcode.log as well as continue logging to the Xcode console (but without colors).

Furthermore in the color log I'm injecting information about the file and class and method that is being called. So if you use it like this:

for (NSString *key in other.allKeys){
    id val = other[key];
    XLog_FB(yellow,blue,@"%@: %@",key,val);
    self[key] = val;
}

You get output that looks like this:

Screen Shot 2019-07-24 at 20 14 39

Or this:

Screen Shot 2019-07-24 at 20 21 11

The first two params are short forms, where say "yellow" will turn into a call to [UIColor yellowColor] and I tried (but didn't really test) to support older ways XCodelogger was logging colors.

So things like:

XLog_ERROR("This error happened: %@",error)

Should work as before. I hope anyway.

It will automatically remove itself when compiling optimized at the macro level. You can pass in various params as shown above to format and log strings.

To view the color log you'd just do this in a terminal window:

tail -f /tmp/xcode.log

And then you have some color logging functionality back on a lightweight basis without having to maintain anything.

All you really need to do is just use the top level functions, there are objects underneath on a singleton basis and using dispatch queues so multiple threads don't interfere and overwrite in the log.

I just slammed this together, so maybe there's bugs still. But you can build on it.

Xlogger.h:

#ifndef XLogger_h
#define XLogger_h

#import <UIKit/UIKit.h>

//  XLogger.h
//
//  Created by Razvan Tanase on 29/06/15.
//  Copyright (c) 2015 Codebringers Software Inc. All rights reserved.
//
//  Version 0.1

#import <Foundation/Foundation.h>

#define XCC_USE_VT 1
// for the future
#ifdef XCC_USE_VT
#  define XCC_ESCAPE @"\033["
#  define XCC_FG_COMMAND "38;2;"
#  define XCC_BG_COMMAND "48;2;"
#  define XCC_COMMIT "m"
#  define XCC_SEP ";"
#  define XCC_RESET XCC_ESCAPE "0" XCC_COMMIT
#  define XCC_RESET_FG  XCC_ESCAPE XCC_FG_COMMAND "0" XCC_COMMIT // Clear any foreground color
#  define XCC_RESET_BG  XCC_ESCAPE XCC_BG_COMMAND "0" XCC_COMMIT // Clear any background color
#endif

// !!!: CHANGE THE TIMESTAMP FORMAT IF NEEDED
static NSString *const kTIMESTAMP_FORMAT = @"HH:mm:ss";

// ???: ADD NEWLINE AFTER EACH OUTPUT?
static BOOL kXLOG_SHOULD_ADD_NEWLINE_AFTER_OUTPUT = NO;

// CHANGE COLORS: RGB FORMAT (fg: text / bg: background)
#pragma mark - COLORS
//default log color

#define XCC_COLOR(r,g,b) [UIColor colorWithRed:r/255. green:g/255. blue:b/255. alpha:1]

#pragma mark - DEFAULT Log Color
//#define kTEXT_COLOR_NO_HIGHLIGHT @"fg0,0,255;"
#define kTEXT_COLOR_NO_HIGHLIGHT XCC_FG(0,0,255)

//text & backgroud colors for INFO Log
#pragma mark - INFO Log Color
//#define kTEXT_COLOR_INFO      @"fg255,255,0;"
#define kTEXT_COLOR_INFO      XCC_COLOR(255,255,0)
#define kBGND_COLOR_INFO      XCC_COLOR(0,0,0)
#define kTEXT_COLOR_INFO2     XCC_COLOR(255,0,255)
#define kBGND_COLOR_INFO2     XCC_COLOR(0,0,0)

#define kTEXT_COLOR_INFO_1    XCC_COLOR(255,255,255)
#define kBGND_COLOR_INFO_1    XCC_COLOR(204,0,204)

//text & backgroud colors for HIGHLIGHT Log
#pragma mark HIGHLIGHT Log Color
#define kTEXT_COLOR_HIGHLIGHT XCC_COLOR(0,255,255)
#define kBGND_COLOR_HIGHLIGHT XCC_COLOR(0,0,0)
#define kTEXT_COLOR_HIGHLIGHT_1 XCC_COLOR(255,255,255)
#define kBGND_COLOR_HIGHLIGHT_1 XCC_COLOR(0,102,51)

//text & backgroud colors for WARNING Log
#pragma mark WARNING Log Color
#define kTEXT_COLOR_WARNING   XCC_COLOR(0,0,0)
#define kBGND_COLOR_WARNING   XCC_COLOR(255,255,0)

//text & backgroud colors for ERROR Log
#pragma mark ERROR Log Color
#define kTEXT_COLOR_ERROR     XCC_COLOR(255,255,255)
#define kBGND_COLOR_ERROR     XCC_COLOR(255,0,0)

#pragma mark MILD Log Color
#define kTEXT_COLOR_MILD XCC_COLOR(66,66,66)
#define kBGND_COLOR_MILD XCC_COLOR(0,0,0)

void _XLog2(UIColor *fg, UIColor *bg, const char *file, long line, const char *function, NSString *output);

#define XCC_NAME(short_name) [UIColor short_name##Color]

#define XLog_FB(fg,bg,output_format, ...) _XLog2(\
XCC_NAME(fg),\
XCC_NAME(bg),\
__FILE__,\
__LINE__,\
__PRETTY_FUNCTION__, \
[NSString stringWithFormat:output_format "", ## __VA_ARGS__]) /* userstuff */

#define XLog_Color(fg,bg,output_format, ...) _XLog2(\
(fg),\
(bg),\
__FILE__,\
__LINE__,\
__PRETTY_FUNCTION__, \
[NSString stringWithFormat:output_format "", ## __VA_ARGS__]) /* userstuff */

#define XLog_FB_nofunc(fg,bg,output_format, ...) _XLog2(\
XCC_NAME(fg),\
XCC_NAME(bg),\
NULL,\
0,\
NULL,\
[NSString stringWithFormat:output_format "", ## __VA_ARGS__]) /* userstuff */

#define XLog_RGB_nofunc(fg,bg,output_format, ...) _XLog2(\
XCC_COLOR(fg),\
XCC_COLOR(bg),\
NULL,\
0,\
NULL,\
[NSString stringWithFormat:output_format "", ## __VA_ARGS__]) /* userstuff */

NSString *timeStamp(void);

#pragma mark - XLOG

#define XLog(s, ...) XLog_Color(nil,nil, s, ##__VA_ARGS__)

//XLog ERROR
#define XLog_ERROR(s, ...) XLog_Color(kTEXT_COLOR_ERROR,kBGND_COLOR_ERROR,s,##__VA_ARGS__)

//XLog INFO
#define XLog_INFO(s, ...) XLog_Color(kTEXT_COLOR_INFO,kBGND_COLOR_INFO,s,##__VA_ARGS__)

#define XLog_INFO2(s, ...) XLog_Color(kTEXT_COLOR_INFO2,kBGND_COLOR_INFO2,s,##__VA_ARGS__)

//XLog HIGHLIGHT
#define XLog_HIGHLIGHT(s, ...) XLog_Color(kTEXT_COLOR_HIGHLIGHT,kBGND_COLOR_HIGHLIGHT,s,##__VA_ARGS__)

//XLog WARNING
#define XLog_WARNING(s, ...) XLog_Color(kTEXT_COLOR_WARNING,kBGND_COLOR_WARNING,s,##__VA_ARGS__)


#define LOGMETHOD     XLog_FB_nofunc(cyan,darkGray,@"-[%s(%p) %s]",object_getClassName(self),self,sel_getName(_cmd));
#define LOGRC()    XLog(@"[(%@ *)%p %s] %u[%c]",object_getClassName(self),self,sel_getName(_cmd),[self retainCount],(_cmd==@selector(retain)?'+':(_cmd==@selector(release)?'-':' ')))

#if defined __OPTIMIZE__
#undef XLog_HIGHLIGHT
#undef XLog_INFO2
#undef XLog_FB
#undef XLog_Color
#undef XLog_INFO
#undef XLog_FB_nofunc
#undef LOGMETHOD
#define LOGMETHOD
#define XLog_FB(a,b,...) if ((0)) NSLog(__VA_ARGS__)
#define XLog_Color(a,b,...) if ((0)) NSLog(__VA_ARGS__)
#define XLog_HIGHLIGHT(...) if ((0)) NSLog(__VA_ARGS__)
#define XLog_INFO2(...) if ((0)) NSLog(__VA_ARGS__)
#define XLog_INFO(...) if ((0)) NSLog(__VA_ARGS__)
#define XLog_FB_nofunc(a,b,...) if ((0)) NSLog(__VA_ARGS__)
#else
#endif


#endif

XLogger.m

#import <Foundation/Foundation.h>

//
//  XLogger.m
//
//  Created by Razvan Tanase on 29/06/15.
//  Copyright (c) 2015 Codebringers Software Inc. All rights reserved.
//

#import "XLogger.h"
#import <UIKit/UIColor.h>

@interface NSString (XLoggerColor)
+ (NSString *)xLoggerRGB:(uint32_t)rgb forTier:(NSString *)tier;
+ (NSString *)xLoggerColor:(UIColor *)color forTier:(NSString *)tier;
@end

@implementation NSString (XLoggerColor)

+ (NSString *)xLoggerRGB:(uint32_t)rgb forTier:(NSString *)tier
{
#if !defined(XCC_DISABLE)
    uint32_t r = ((rgb & 0xff0000) >> 16);
    uint32_t g = ((rgb & 0x00ff00) >> 8);
    uint32_t b = (rgb & 0x0000ff);
    return [NSString stringWithFormat:XCC_ESCAPE@"%@%d" XCC_SEP "%d" XCC_SEP "%d" XCC_COMMIT,tier,r,g,b];
#else
    return @"";
#endif
}

+ (NSString *)xLoggerColor:(UIColor *)color forTier:(NSString *)tier
{
#if !defined(XCC_DISABLE)
    uint32_t rgb = 0;
    CGFloat red, green, blue, alpha;
    [color getRed:&red green:&green blue:&blue alpha:&alpha];
    rgb |= ((unsigned)(blue*255.));
    rgb |=(((unsigned)(green*255.))<<8);
    rgb |=(((unsigned)(red*255.))<<16);
    return [self xLoggerRGB:rgb forTier:tier];
#else
    return @"";
#endif
}

#define XCC_ANSI_FG XCC_ESCAPE "38;5;"
#define XCC_ANSI_BG XCC_ESCAPE "48;5;"

static inline NSString *
xLoggerANSI(uint32_t ansi, NSString *tier)
{
#if !defined(XCC_DISABLE)
    return [NSString stringWithFormat:@"%@%d" XCC_COMMIT,tier,ansi];
#else
    return @"";
#endif
}

static inline unsigned
ansiForRedGreenBlue(unsigned r, unsigned g, unsigned b)
{
    double result;
    if (r == g && g == b) {
        if (r < 8) {
            return 16;
        }
        if (r > 248) {
            return 231;
        }
        result = round(((r - 8) / 247.) * 24) + 232;
    } else {
        result = 16
        + (36 * round(r / 255. * 5))
        + (6 * round(g / 255. * 5))
        + round(b / 255. * 5);
    }
    return (unsigned)result;
}

+ (NSString *)xLoggerANSI:(UIColor *)color forTier:(NSString *)tier
{
#if !defined(XCC_DISABLE)
    CGFloat red, green, blue, alpha;
    [color getRed:&red green:&green blue:&blue alpha:&alpha];
    red*=256;
    green*=256;
    blue*=256;
    return [self xLoggerANSI:red :green :blue forTier:tier];
#else
    return @"";
#endif
}


+ (NSString *)xLoggerANSI:(unsigned)red :(unsigned)green :(unsigned)blue forTier:(NSString *)tier
{
#if !defined(XCC_DISABLE)
    unsigned ansi = ansiForRedGreenBlue(red,green,blue);
    NSString *code = xLoggerANSI(ansi,tier);
    return code;
#else
    return @"";
#endif
}

@end

@interface XLogger : NSObject
{
    FILE *_logfile;
    dispatch_queue_t _queue;
}
@end

@implementation XLogger

#pragma mark - Singleton Junk

+ (instancetype)sharedLogger;
{
    static XLogger *logger = nil;
    static dispatch_once_t otoken;
    dispatch_once(&otoken, ^{
        logger = [[XLogger alloc] init];
    });
    return logger;
}

- (unsigned long)retainCount {
    return UINT_MAX;  // denotes an object that cannot be released
}

- (oneway void)release {
    // do nothing
}

- (id)autorelease {
    return self;
}

- (instancetype)init;
{
    if ((self = [super init])){
        _queue = dispatch_queue_create("XLogger", DISPATCH_QUEUE_CONCURRENT);
        _logfile =  fopen("/tmp/xcode.log","a");
    }
    return self;
}
- (void)_log:(NSString *)fgc :(NSString *)bgc :(NSString *)output :(FILE *)standardLog :(FILE *)colorLog
{
    if (!output) {
        return;
    }
    dispatch_sync(_queue, ^{
        const char *msg = NULL;
        if (standardLog) {
            msg = output.UTF8String;
            fputs(msg, stdout);
            fputs("\n",stdout);
        }
        if (colorLog) {
            if (fgc || bgc) {
                NSString *formatted = [NSString stringWithFormat:@"%@%@%@" XCC_RESET "\n",fgc?fgc:@"",bgc?bgc:@"",output];
                msg = formatted.UTF8String;
            } else if (!msg) {
                msg = output.UTF8String;
            }
            fputs(msg,colorLog);
            fflush(colorLog);
        }
    });
}

- (void)logfileAndXCode:(NSString *)fgc :(NSString *)bgc :(NSString *)output;
{
    [self _log:fgc :bgc :output :stdout :_logfile];
}

- (void)logfileOnly:(NSString *)fgc :(NSString *)bgc :(NSString *)output;
{
    [self _log:fgc :bgc :output :NULL :_logfile];
}

- (void)xcodeOnly:(NSString *)fgc :(NSString *)bgc :(NSString *)output;
{
    [self _log:fgc :bgc :output :stdout :NULL];
}

void _XLog2(UIColor *fg, UIColor *bg, const char *file, long line, const char *function, NSString *output)
{
    XLogger *log = XLogger.sharedLogger;
    if (function) {
        NSString *color = [NSString xLoggerANSI:66 :66 :66 forTier:XCC_ANSI_FG];
        NSString *trimmedFile = [[NSString stringWithUTF8String:file] lastPathComponent];
        NSString *fileinfo = [NSString stringWithFormat:@"%@:%ld:%s", trimmedFile,line,function];
        [log logfileOnly:color :nil :fileinfo];
    }
    NSString *fgc = [NSString xLoggerANSI:fg forTier:XCC_ANSI_FG];
    NSString *bgc = [NSString xLoggerANSI:bg forTier:XCC_ANSI_BG];
    [log logfileAndXCode:fgc :bgc :output];
}


NSString *timeStamp(void) {
    NSDate *currentTime = [NSDate date];
    
    static NSDateFormatter *dateFormatter;
    
    if (!dateFormatter) {
        dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:kTIMESTAMP_FORMAT];
    }
    
    return [dateFormatter stringFromDate: currentTime];
}

@end

from xcodecolors.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.