I'm writing a Cocoa application in Objective-C, and I would like to be able to incorporate Markdown. The user will enter text in Markdown syntax, click an "export" button, and the program will output a file of XHTML.
It seems like there are a lot of options, though. I could use one of the C/C++ implementations, I could run the Perl script as a resource to my Cocoa app, I assume could use the Python implementation and the PyObjC bridge or the Perl implementation and the CamelBones or PerlObjC bridges. What would be the simplest and easiest solution? I'm not doing anything complicated like a real-time rendered preview that would require threading.
I had a look at the various options, and in the end found libsoldout, a very small C implementation that's quite easy to integrate. You just need to include array.[ch], buffer.[ch], markdown.[ch], and renderers.[ch] in your Xcode project, then you can convert an NSString from markdown to HTML like so:
NSString *rawMarkdown;
const char * prose = [rawMarkdown UTF8String];
struct buf *ib, *ob;
int length = rawMarkdown.length + 1;
ib = bufnew(length);
bufgrow(ib, length);
memcpy(ib->data, prose, length);
ib->size = length;
ob = bufnew(64);
markdown(ob, ib, &mkd_xhtml);
NSString *shinyNewHTML = [NSString stringWithUTF8String: ob->data];
NSLog(#"%#", shinyNewHTML);
bufrelease(ib);
bufrelease(ob);
I just used the Sundown implementation which includes SmartyPants support, in an iPad app with great success. Took about 15 minutes to build a test app.
Assume you have a UITextView *textView (which you setDelegate:self) and also a UIWebView *webView in which to display the results:
- (void) textViewDidEndEditing:(UITextView *)textView
{
NSString *rawMarkdown = [textView text];
const char * prose = [rawMarkdown UTF8String];
struct buf *ib, *ob;
int length = [rawMarkdown lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1;
ib = bufnew(length);
bufgrow(ib, length);
memcpy(ib->data, prose, length);
ib->size = length;
ob = bufnew(64);
struct sd_callbacks callbacks;
struct html_renderopt options;
struct sd_markdown *markdown;
sdhtml_renderer(&callbacks, &options, 0);
markdown = sd_markdown_new(0, 16, &callbacks, &options);
sd_markdown_render(ob, ib->data, ib->size, markdown);
sd_markdown_free(markdown);
NSString *shinyNewHTML = [NSString stringWithUTF8String: ob->data];
[webView loadHTMLString:shinyNewHTML baseURL:[[NSURL alloc] initWithString:#""]];
bufrelease(ib);
bufrelease(ob);
}
You may want to check out the open-source app Macdown which I wrote (or alternatively rentzsch's Markdownlive), which incorporate this functionality as the sole purpose of the two apps.
I found problems with processing large amounts of markdown with these C-based libraries.
There's a very simple Obj-C library that worked for me here:
https://github.com/mdiep/MMMarkdown
Steps to use MMMarkdown:
Build the OS X or iOS target
Copy include/MMMarkdown.h and either
lib/libMMMarkdown-Mac.a or lib/libMMMarkdown-iOS.a into your project
Then the code is:
#import "MMMarkdown.h"
NSError *error;
NSString *markdown = #"# Example\nWhat a library!";
NSString *htmlString = [MMMarkdown HTMLStringWithMarkdown:markdown error:&error];
// Returns #"<h1>Example</h1>\n<p>What a library!</p>"
I've used peg-markdown, it's much faster than the original perl and can handle a few syntax extensions if you enable them.
Oliver Letterer's GHMarkdownParser translate markdown to HTML.
Phil Toland's QLMarkdown QuickLook generator for markdown files.
Related
The following fails for both unichar assignments?
unsigned int c = 0x0001d122;
[NSString stringWithFormat:#"\U%#", [NSString stringWithFormat:#"%08X", c]];
[NSString stringWithFormat:#"\U%08X", c];
I am trying to do this programmatically (adding in the "\U" makes things difficult as seen above):
nssSymbol = #"\U0001d122"; \\this works... but need to be able to vary 'c'
As shown by Ken Thomases answer you can create a string from bytes, however you must know the endianness of your machine or use the endian conversion routines.
For example, on an Intel Mac which is little endian you can use:
uint32_t c = 0x0001d122;
NSString* s = [[NSString alloc] initWithBytes:&c
length:sizeof(c)
encoding:NSUTF32LittleEndianStringEncoding];
If you don't wish to code in knowledge of the systems endianness you can use the conversion routines. For example:
uint32_t c = EndianU32_NtoB(0x0001d122); // convert from native endianness to big endian
NSString* s = [[NSString alloc] initWithBytes:&c
length:sizeof(c)
encoding:NSUTF32BigEndianStringEncoding];
HTH
The handling of the \Unnnnnnnn construct in a string literal is done at compile time. You can't build the construct at run time and have it interpreted. That's not how things work.
You could do:
uint32_t c = 0x0001d122;
NSString* s = [[NSString alloc] initWithBytes:&c length:sizeof(c) encoding:NSUTF32LittleEndianStringEncoding];
I am using OpenCV in a iPhone project. In this application, I receive a 3x3 matrix from the Opencv function an need to transform it into a NSString. For example:
cv::Mat myMatrix = opencvClass.getMatrix();
NSString *matrixString = myMatrix.toNSString(); // this function does not exist actually but it is what I need
Any suggestions?
Cheers,
I guess you could convert it to a std::stringstream, extract the C array of bytes from it and use this to contruct your NSString :
NSString NSStringFromCvMat(cv::Mat mat)
{
std::stringstream ss;
ss << mat;
return [NSString stringWithCString:ss.str().c_str() encoding:NSASCIIStringEncoding];
}
Untested but should work. The encoding could be a problem. Maybe try different values.
I don't think it is the best solution though, and you could find a beter and cleaner one by diving into OpenCV source code.
I honestly did a) search using key words and b) read the 'questions with similar titles' before asking this.
Also I tried to make this question more concise, but I had a hard time doing that in this case. If you feel the question is too wordy, I get it. Just don't try to answer.
I'm trying to write very simple objective-C programs that mirror the basic assignments in my introductory java class. I worked through an objective-c book over the summer and now I want to do lots of practice problems in objective-c, at the same time as I do java practice problems. I'm avoiding the objective-c GUI environment and just want to focus on working with the language for awhile. I still have a lot to learn about how to figure things out.
The program I'm duplicating from my java homework, is a standard type. I ask the user for number input and string input via the console. I was able to get numeric input from the console using an example I found here using scan f. (I will put the couple code lines below). But I'm unsure on how to get console input and store it in a string (NSString). I'm trying to learn to use the apple documentation and found a reference to a scan type command, but I cannot figure out how to USE the command. The one that seems likely is
scanCharactersFromSet:(NSCharacterSet )scanSet intoString:(NSString *)name;
Here's what I understand and works
int age = 0;
NSLog (#"How old are y'all?");
scanf("%d", &age);
NSLog (#"\n Wow, you are %d !", age);
But I don't understand how to pickup an NSString called 'name'. I THINK I'm supposed to make my 'name'a pointer, because the class is NSString.
(BTW I did try using scanf to pickup the string, but the compiler doesn't like me trying to use scanf in conjunction with name. It says that I shouldn't be using 'scanf' because it's expecting a different kind of data. I'm not sure where I found the data type 'i'. I was looking through my text for different ideas. I'm guessing that scanf is related to 'scanfloat' which clearly deals with numeric data, so this is not a big surprise)
I realize that 'scanf' isn't the right command (and I don't really get why I can't even find scanf in the apple documentation - maybe it's C?)
I'm guessing that scanCharactersFromSet might be the right thing to use, but I just don't understand how you figure out what goes where in the command. I guess I tend to learn by example, and I haven't found an example. I'd like to figure out how to learn properly by reading the documentation. But I'm not there yet.
NSString* name ;
scanf("%i", &name);
//scanCharactersFromSet:(NSCharacterSet *)scanSet intoString:(NSString **)name;
...
My book is oriented towards moving me into a gui environment, so it doesn't deal with input.
Thank you for any pointers you can give me.
Laurel
I would recommend ramping up on C. Objective-c is a thin layer over C and that knowledge will pay for itself over and over.
There's multiple ways in C to read:
http://www.ehow.com/how_2086237_read-string-c.html
For example:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
char str[50] = {0}; // init all to 0
printf("Enter you Last name: ");
scanf("%s", str); // read and format into the str buffer
printf("Your name is %s\n", str); // print buffer
// you can create an NS foundation NSString object from the str buffer
NSString *lastName = [NSString stringWithUTF8String:str];
// %# calls description o object - in NSString case, prints the string
NSLog(#"lastName=%#", lastName);
[pool drain];
return 0;
NOTE: the simple scanf is succeptible to buffer overruns. There's multiple approaches around this. see:
How to prevent scanf causing a buffer overflow in C?
Here is what Objective C looks like:
NSString *FNgetInput() {
#autoreleasepool {
return [[[NSString alloc] initWithData:[[NSFileHandle fileHandleWithStandardInput] availableData] encoding:NSUTF8StringEncoding] stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
}
}
The way to get data from the standard input (or any other file handle) in cocoa is to use the NSFileHandle class. Check the docs for +fileHandleWithStandardInput
Here's how to get user input using Objective-C in 2020:
main.m
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
char str[50] = {0}; // init all to 0
printf("Enter you Last name: ");
scanf("%s", str); // read and format into the str buffer
printf("Your name is %s\n", str); // print buffer
// you can create an NS foundation NSString object from the str buffer
NSString *lastName = [NSString stringWithUTF8String:str];
// %# calls description o object - in NSString case, prints the string
NSLog(#"lastName=%#", lastName);
return 0;
}
return 0;
}
Compile and run:
$ clang -framework Foundation main.m -o app
I need to view data from NSMutableArray in NSTableView. There is the code:
- (IBAction)StartReconstruction:(id)sender
{
NSMutableArray *ArrayOfFinals = [[NSMutableArray alloc] initWithObjects:nil]; //Array of list with final images
NSString *FinalPicture;
NSString *PicNum;
int FromLine = [TextFieldFrom intValue]; //read number of start line
int ToLine = [TextFieldTo intValue]; //read number of finish line
int RecLine;
for (RecLine = FromLine; RecLine < ToLine; RecLine++) //reconstruct from line to line
{
//Start(RecLine); //start reconstruction
//Create path of final image
FinalPicture = #"FIN/final";
PicNum = [NSString stringWithFormat: #"%d", RecLine];
FinalPicture = [FinalPicture stringByAppendingString:PicNum];
FinalPicture = [FinalPicture stringByAppendingString:#".bmp"];
[ArrayOfFinals addObject:FinalPicture]; // add path to array
}
NSBeep(); //make some noise
}
I need to set ArrayOfFinals as data source for my tableview in my app. I'm noob in cocoa, and I don't know where I need to make connections :(
I saw tutorial on youtube, but it didn't hepl me.
SO is really not a place for step-by-step tutorials.
But on this subject there're many you can find online. Personally, I've found apple tutorial very informative (even if a bit verbose).
You can't really use an array directly as a data source, but you can use an NSArrayController in between and then use bindings to hook them up.
You won't need to write a single line of code for a basic set up.
There are plenty of step-by-step tutorials on the net for this.
I have been able to find methods like -[NSString stringWithCString:encoding:] but they do not seem to play well when the cstring is a pointer.
First up, don't use initWithCString, it has been deprecated.
Couple of ways you can do this:
const *char cString = "Hello";
NSString *myNSString = [NSString stringWithUTF8String:cString];
If you need another encoding like ASCII:
const *char cString = "Hello";
NSString *myNSString = [NSString stringWithCString:cString encoding:NSASCIIStringEncoding];
If you want to see all the string encodings available, in Xcode, hold command + option then double click on NSASCIIStringEncoding in the above code block.
You will be able to see where Apple have declared their enumeration for the string encoding types. Bit quicker than trying to find it in the documentation.
Some other ones you might need:
NSASCIIStringEncoding
NSUnicodeStringEncoding // same as NSUTF16StringEncoding
NSUTF32StringEncoding
Checkout Apple's NSString Class Reference (encodings are at the bottom of the page)
With modern Objective-C (since Xcode 5 at least) you can just do:
char const* cString = "Hello";
NSString *myNSString = #(cString);
stringWithCString:encoding: creates an NSString from a given C string. To create a C string from an NSString, use either the UTF8String method (generally preferred) or cStringUsingEncoding: (if you need an encoding other than UTF-8).