是否有类似ruby的'expect.rb',但对于Objective C?

时间:2011-04-23 20:02:26

标签: objective-c c expect

我知道libexpect,但它的来源很大,需要tcl。我希望能像红宝石的'expect.rb'一样小,这是一个小文件。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

您可以考虑将macruby用于项目。

答案 1 :(得分:1)

解决了它。我根本没有运行libexpect。相反,我刚刚使用expect.rb将rubys'CocoaOniguruma'移植到objective-c。随意使用它。


/*
NSFileHandle+Expect.h
direct port of rubys 'expect.rb' to objective c
by Simon Strandgaard on 26/04/11.
public domain or BSD license

requires CocoaOniguruma
http://limechat.net/cocoaoniguruma/
*/
#import <Foundation/Foundation.h>


@class ExpectResult;

@interface NSFileHandle (Expect)

/*
wait for activity on the file descriptor.
stops waiting if it takes longer than X seconds.
*/
-(BOOL)waitForData:(float)seconds;


/*
buffer data on the filedescriptor until it matches the specified pattern.
*/
-(ExpectResult*)expect:(NSString*)pattern timeout:(float)seconds debug:(BOOL)debug;


/*
write to filedescriptor
*/
-(void)writeAsciiString:(NSString*)s;

@end

/*
NSFileHandle+Expect.m
direct port of rubys 'expect.rb' to objective c
by Simon Strandgaard on 26/04/11.
public domain or BSD license

requires CocoaOniguruma
http://limechat.net/cocoaoniguruma/
*/
#import "NSFileHandle+Expect.h"
#import "OnigRegexp.h"
#import "ExpectResult.h"


@implementation NSFileHandle (Expect)

-(BOOL)waitForData:(float)seconds {
    struct timeval t; 
    t.tv_sec = (int)seconds;
    float remain = seconds - t.tv_sec;
    t.tv_usec = (int)(remain * 1000000);


    int fd = [self fileDescriptor];
    fd_set ready; 
    FD_ZERO(&ready); 
    FD_SET((unsigned int)fd, &ready); 

    int res = select(fd+1, &ready, NULL, NULL, &t); 
    if(res == 0) {
        return NO; // timeout
    }
    if(FD_ISSET(fd, &ready)) {
        return YES; // we have data, one or more bytes is ready
    }
    return NO; // error
}


-(ExpectResult*)expect:(NSString*)pattern timeout:(float)seconds debug:(BOOL)debug {
    OnigRegexp* regexp = [OnigRegexp compile:pattern];
    NSMutableString* buffer = [NSMutableString stringWithCapacity:100];
    ExpectResult* result = nil;
    while(1) {
        // wait until 1 byte is ready
        if(![self waitForData:seconds]) {
            // timeout or error
            result = nil;
            break;
        }

        // read out the byte and append it to the buffer
        NSData* char_data = [self readDataOfLength:1];
        NSString* char_string = [[NSString alloc] initWithData:char_data encoding: NSASCIIStringEncoding];
        [buffer appendString:char_string];
        if(debug) {
            NSLog(@"%s %@", _cmd, char_string);
        }
        [char_string release];

        // see if the new buffer now satisfies the pattern
        OnigResult* r = [regexp search:buffer];
        if(r) {
            result = [[[ExpectResult alloc] init] autorelease];
            result.bufferString = [NSString stringWithString:buffer];
            result.onigResult = r;
            break;
        }
    }

    return result;
}

-(void)writeAsciiString:(NSString*)s {
    [self writeData:[s dataUsingEncoding:NSASCIIStringEncoding]];   
}

@end

/*
ExpectResult.h
direct port of rubys 'expect.rb' to objective c
by Simon Strandgaard on 26/04/11.
public domain or BSD license

requires CocoaOniguruma
http://limechat.net/cocoaoniguruma/
*/
#import <Foundation/Foundation.h>

@class OnigResult;

@interface ExpectResult : NSObject {
    NSString* m_buffer_string;
    OnigResult* m_onig_result;
}
@property (nonatomic, retain) NSString* bufferString;
@property (nonatomic, retain) OnigResult* onigResult;

@end

/*
ExpectResult.h
direct port of rubys 'expect.rb' to objective c
by Simon Strandgaard on 26/04/11.
public domain or BSD license

requires CocoaOniguruma
http://limechat.net/cocoaoniguruma/
*/
#import "ExpectResult.h"
#import "OnigRegexp.h"

@implementation ExpectResult

@synthesize bufferString = m_buffer_string;
@synthesize onigResult = m_onig_result;

-(void)dealloc {
    self.bufferString = nil;
    self.onigResult = nil;
    [super dealloc];
}

@end

NSArray* arguments = [NSArray arrayWithObject:@"ftp.ruby-lang.org"];

NSTask* task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:@"/usr/bin/ftp"];

NSPipe* readPipe = [NSPipe pipe];
NSPipe* writePipe = [NSPipe pipe];

[task setStandardInput: writePipe];
[task setStandardOutput: readPipe];
[task setArguments:arguments];

[task launch];

NSFileHandle* readHandle = [readPipe fileHandleForReading];
NSFileHandle* writeHandle = [writePipe fileHandleForWriting];

{
    NSString* pattern = @"^Name.*: ";
    [readHandle expect:pattern timeout:5 debug:YES];
    [writeHandle writeAsciiString:@"ftp\n"];
}
{
    NSString* pattern = @"word:";
    [readHandle expect:pattern timeout:5 debug:YES];
    [writeHandle writeAsciiString:@"guest@\n"];
}
{
    NSString* pattern = @"> ";
    [readHandle expect:pattern timeout:5 debug:YES];
    [writeHandle writeAsciiString:@"cd pub/ruby\n"];
}
{
    NSString* pattern = @"> ";
    [readHandle expect:pattern timeout:5 debug:YES];
    [writeHandle writeAsciiString:@"dir\n"];
}
{
    NSString* pattern = @"> ";
    ExpectResult* er = [readHandle expect:pattern timeout:5 debug:YES];

    NSLog(@"%s versions: %@", _cmd, er.bufferString);

    [writeHandle writeAsciiString:@"quit\n"];
}

output:
drwxrwxr-x    2 0        103          4096 Jul 06  2009 1.0
drwxrwxr-x    2 0        103          4096 Aug 04  2003 1.1a
drwxrwxr-x    2 0        103          4096 Jul 16  1998 1.1b
drwxrwxr-x    2 0        103          4096 Jan 18  1999 1.1c
drwxrwxr-x    2 0        103            54 Dec 25  1998 1.1d
drwxrwxr-x    2 0        103          4096 Sep 18  1999 1.2
drwxrwxr-x    2 0        103          4096 Sep 18  1999 1.3
drwxrwxr-x    2 0        103          4096 Apr 05  2001 1.4
drwxrwxr-x    2 0        103          4096 Sep 20  2005 1.6
drwxrwxr-x    2 0        103          8192 Feb 18 12:49 1.8
drwxrwxr-x    2 0        103          4096 Feb 18 13:39 1.9
drwxrwxr-t    6 0        103            89 Jun 15  2004 binaries
drwxrwxr-x    2 1027     100         12288 Apr 05 15:12 doc
lrwxrwxrwx    1 1023     100            27 Sep 23  2010 ruby-1.8.6-p420.tar.bz2 ->