mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
cleanup Nim's examples/ directory; closes #7725
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
# Horrible example of how to interface with a C++ engine ... ;-)
|
||||
|
||||
{.link: "/usr/lib/libIrrlicht.so".}
|
||||
|
||||
{.emit: """
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
using namespace scene;
|
||||
using namespace video;
|
||||
using namespace io;
|
||||
using namespace gui;
|
||||
""".}
|
||||
|
||||
const
|
||||
irr = "<irrlicht/irrlicht.h>"
|
||||
|
||||
type
|
||||
TDimension2d {.final, header: irr, importc: "dimension2d".} = object
|
||||
Tvector3df {.final, header: irr, importc: "vector3df".} = object
|
||||
TColor {.final, header: irr, importc: "SColor".} = object
|
||||
|
||||
TIrrlichtDevice {.final, header: irr, importc: "IrrlichtDevice".} = object
|
||||
TIVideoDriver {.final, header: irr, importc: "IVideoDriver".} = object
|
||||
TISceneManager {.final, header: irr, importc: "ISceneManager".} = object
|
||||
TIGUIEnvironment {.final, header: irr, importc: "IGUIEnvironment".} = object
|
||||
TIAnimatedMesh {.final, header: irr, importc: "IAnimatedMesh".} = object
|
||||
TIAnimatedMeshSceneNode {.final, header: irr,
|
||||
importc: "IAnimatedMeshSceneNode".} = object
|
||||
TITexture {.final, header: irr, importc: "ITexture".} = object
|
||||
|
||||
PIrrlichtDevice = ptr TIrrlichtDevice
|
||||
PIVideoDriver = ptr TIVideoDriver
|
||||
PISceneManager = ptr TISceneManager
|
||||
PIGUIEnvironment = ptr TIGUIEnvironment
|
||||
PIAnimatedMesh = ptr TIAnimatedMesh
|
||||
PIAnimatedMeshSceneNode = ptr TIAnimatedMeshSceneNode
|
||||
PITexture = ptr TITexture
|
||||
|
||||
proc dimension2d(x, y: cint): TDimension2d {.
|
||||
header: irr, importc: "dimension2d<u32>".}
|
||||
proc vector3df(x,y,z: cint): Tvector3df {.
|
||||
header: irr, importc: "vector3df".}
|
||||
proc SColor(r,g,b,a: cint): TColor {.
|
||||
header: irr, importc: "SColor".}
|
||||
|
||||
proc createDevice(): PIrrlichtDevice {.
|
||||
header: irr, importc: "createDevice".}
|
||||
proc run(device: PIrrlichtDevice): bool {.
|
||||
header: irr, importcpp: "run".}
|
||||
|
||||
proc getVideoDriver(dev: PIrrlichtDevice): PIVideoDriver {.
|
||||
header: irr, importcpp: "getVideoDriver".}
|
||||
proc getSceneManager(dev: PIrrlichtDevice): PISceneManager {.
|
||||
header: irr, importcpp: "getSceneManager".}
|
||||
proc getGUIEnvironment(dev: PIrrlichtDevice): PIGUIEnvironment {.
|
||||
header: irr, importcpp: "getGUIEnvironment".}
|
||||
|
||||
proc getMesh(smgr: PISceneManager, path: cstring): PIAnimatedMesh {.
|
||||
header: irr, importcpp: "getMesh".}
|
||||
|
||||
proc drawAll(smgr: PISceneManager) {.
|
||||
header: irr, importcpp: "drawAll".}
|
||||
proc drawAll(guienv: PIGUIEnvironment) {.
|
||||
header: irr, importcpp: "drawAll".}
|
||||
|
||||
proc drop(dev: PIrrlichtDevice) {.
|
||||
header: irr, importcpp: "drop".}
|
||||
|
||||
proc getTexture(driver: PIVideoDriver, path: cstring): PITexture {.
|
||||
header: irr, importcpp: "getTexture".}
|
||||
proc endScene(driver: PIVideoDriver) {.
|
||||
header: irr, importcpp: "endScene".}
|
||||
proc beginScene(driver: PIVideoDriver, a, b: bool, c: TColor) {.
|
||||
header: irr, importcpp: "beginScene".}
|
||||
|
||||
proc addAnimatedMeshSceneNode(
|
||||
smgr: PISceneManager, mesh: PIAnimatedMesh): PIAnimatedMeshSceneNode {.
|
||||
header: irr, importcpp: "addAnimatedMeshSceneNode".}
|
||||
|
||||
proc setMaterialTexture(n: PIAnimatedMeshSceneNode, x: cint, t: PITexture) {.
|
||||
header: irr, importcpp: "setMaterialTexture".}
|
||||
proc addCameraSceneNode(smgr: PISceneManager, x: cint, a, b: TVector3df) {.
|
||||
header: irr, importcpp: "addCameraSceneNode".}
|
||||
|
||||
|
||||
var device = createDevice()
|
||||
if device == nil: quit "device is nil"
|
||||
|
||||
var driver = device.getVideoDriver()
|
||||
var smgr = device.getSceneManager()
|
||||
var guienv = device.getGUIEnvironment()
|
||||
|
||||
var mesh = smgr.getMesh("/home/andreas/download/irrlicht-1.7.2/media/sydney.md2")
|
||||
if mesh == nil:
|
||||
device.drop()
|
||||
quit "no mesh!"
|
||||
|
||||
var node = smgr.addAnimatedMeshSceneNode(mesh)
|
||||
|
||||
if node != nil:
|
||||
#node->setMaterialFlag(EMF_LIGHTING, false)
|
||||
#node->setMD2Animation(scene::EMAT_STAND)
|
||||
node.setMaterialTexture(0,
|
||||
driver.getTexture(
|
||||
"/home/andreas/download/irrlicht-1.7.2/media/media/sydney.bmp"))
|
||||
|
||||
smgr.addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0))
|
||||
while device.run():
|
||||
driver.beginScene(true, true, SColor(255,100,101,140))
|
||||
smgr.drawAll()
|
||||
guienv.drawAll()
|
||||
driver.endScene()
|
||||
device.drop()
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import BaseHTTPServer
|
||||
import CGIHTTPServer
|
||||
|
||||
server = BaseHTTPServer.HTTPServer
|
||||
handler = CGIHTTPServer.CGIHTTPRequestHandler
|
||||
server_address = ('localhost', 8008)
|
||||
handler.cgi_directories = ['/']
|
||||
|
||||
httpd = server(server_address, handler)
|
||||
httpd.serve_forever()
|
||||
@@ -1,5 +0,0 @@
|
||||
import cgi
|
||||
cgi.setStackTraceStdout()
|
||||
|
||||
var a: string = nil
|
||||
a.add "foobar"
|
||||
@@ -1,7 +0,0 @@
|
||||
import cgi
|
||||
|
||||
write(stdout, "Content-type: text/html\n\n")
|
||||
write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n")
|
||||
write(stdout, "<html><head><title>Test</title></head><body>\n")
|
||||
write(stdout, "Hello!")
|
||||
writeLine(stdout, "</body></html>")
|
||||
@@ -1,12 +0,0 @@
|
||||
# Test/show CGI module
|
||||
import strtabs, cgi
|
||||
|
||||
var myData = readData()
|
||||
validateData(myData, "name", "password")
|
||||
writeContentType()
|
||||
|
||||
write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n")
|
||||
write(stdout, "<html><head><title>Test</title></head><body>\n")
|
||||
writeLine(stdout, "name: " & myData["name"])
|
||||
writeLine(stdout, "password: " & myData["password"])
|
||||
writeLine(stdout, "</body></html>")
|
||||
12
examples/cross_calculator/.gitignore
vendored
12
examples/cross_calculator/.gitignore
vendored
@@ -1,12 +0,0 @@
|
||||
# Android specific absolute paths.
|
||||
android/bin/
|
||||
android/gen/
|
||||
android/jni/backend-jni.h
|
||||
android/libs/
|
||||
android/local.properties
|
||||
android/obj/
|
||||
android/tags
|
||||
# iOS specific absolute paths
|
||||
ios/resources/ui/*.m
|
||||
ios/tags
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.nimrod.crosscalculator"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="3" />
|
||||
|
||||
<application android:label="@string/app_name" android:debuggable="true">
|
||||
<activity android:name=".CrossCalculator"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -1,92 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="CrossCalculator" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="custom_rules" default="debug">
|
||||
<target name="nim">
|
||||
<exec executable="scripts/nimbuild.sh" failonerror="true">
|
||||
</exec>
|
||||
</target>
|
||||
<target name="jni">
|
||||
<exec executable="scripts/jnibuild.sh" failonerror="true">
|
||||
</exec>
|
||||
</target>
|
||||
<target name="ndk">
|
||||
<exec executable="ndk-build" failonerror="true">
|
||||
</exec>
|
||||
</target>
|
||||
<target name="-post-compile" depends="nim, jni, ndk">
|
||||
</target>
|
||||
</project>
|
||||
@@ -1,32 +0,0 @@
|
||||
# Copyright (C) 2009 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := nimrod
|
||||
LOCAL_SRC_FILES := nimcache/backend.c nimcache/system.c
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/nimcache
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := backend-jni
|
||||
LOCAL_SRC_FILES := backend-jni.c
|
||||
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
|
||||
LOCAL_STATIC_LIBRARIES := nimrod
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include "backend-jni.h"
|
||||
#include "backend.h"
|
||||
|
||||
#define TAG "backend-jni.c"
|
||||
|
||||
jint JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_myAdd
|
||||
(JNIEnv *env, jobject thiz, jint a, jint b)
|
||||
{
|
||||
char buf[256];
|
||||
const jint ret = myAdd(a, b);
|
||||
// Using logging from inside the native bridge to log-debug.
|
||||
sprintf(buf, "a %d + b %d = ret %d", a, b, ret);
|
||||
__android_log_write(ANDROID_LOG_DEBUG, TAG, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_initNimMain
|
||||
(JNIEnv *env, jclass thiz)
|
||||
{
|
||||
NimMain();
|
||||
__android_log_write(ANDROID_LOG_DEBUG, TAG, "Nimrod initialised");
|
||||
}
|
||||
|
||||
// vim:tabstop=2 shiftwidth=2 syntax=c
|
||||
@@ -1,14 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-3
|
||||
@@ -1,24 +0,0 @@
|
||||
In this directory you will find the Android platform cross-calculator sample.
|
||||
|
||||
Due to the nature of Android being java and Nim generating C code, the build
|
||||
process is slightly more complex because jni code has to be written to bridge
|
||||
both languages. In a distant future it may be possible for Nim to generate
|
||||
the whole jni bridge, but for the moment this is manual work.
|
||||
|
||||
For the jni bridge to work first the java code is compiled with the Nim code
|
||||
just declared as a native method which will be resolved at runtime. The scripts
|
||||
nimbuild.sh and jnibuild.sh are in charge of building the Nim code and
|
||||
generating the jni bridge from the java code respectively. Finally, the
|
||||
ndk-build command from the android ndk tools has to be run to build the binary
|
||||
library which will be installed along the final apk.
|
||||
|
||||
All these steps are wrapped in the ant build script through the customization
|
||||
of the -post-compile rule. If you have the android ndk tools installed and you
|
||||
modify scripts/nimbuild.sh to point to the directory where you have Nim
|
||||
installed on your system, you can simply run "ant debug" to build everything.
|
||||
|
||||
Once the apk is built you can install it on your device or emulator with the
|
||||
command "adb install bin/CrossCalculator-debug.apk".
|
||||
|
||||
This example runs against the Android level 3 API, meaning devices from
|
||||
Android 1.5 and above should be able to run the generated binary.
|
||||
@@ -1,72 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/RelativeLayout1"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="Crossplatform Nimrod calculator"
|
||||
android:textSize="20dip" >
|
||||
|
||||
</TextView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_a"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/title"
|
||||
android:text="Value A: " >
|
||||
</TextView>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_text_a"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/title"
|
||||
android:ems="10"
|
||||
android:inputType="number" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value_b"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/edit_text_a"
|
||||
android:text="Value B: " >
|
||||
</TextView>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_text_b"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/edit_text_a"
|
||||
android:ems="10"
|
||||
android:inputType="number" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_button"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@+id/edit_text_b"
|
||||
android:scrollbarAlwaysDrawVerticalTrack="false"
|
||||
android:selectAllOnFocus="false"
|
||||
android:text="Add!"
|
||||
android:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@+id/add_button" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">CrossCalculator</string>
|
||||
</resources>
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Force errors to fail script.
|
||||
set -e
|
||||
|
||||
# If we are running from inside the scripts subdir, get out.
|
||||
if [ ! -d src ]
|
||||
then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# Ok, are we out now?
|
||||
if [ -d src ]
|
||||
then
|
||||
javah -classpath bin/classes \
|
||||
-o jni/backend-jni.h \
|
||||
com.github.nimrod.crosscalculator.CrossCalculator
|
||||
else
|
||||
echo "Uh oh, bin/classes directory not found?"
|
||||
echo "Try compiling your java code, or opening in eclipse."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set this to the local or full path of your nimrod compiler
|
||||
PATH_TO_NIMROD=~/project/nimrod/bin/nimrod
|
||||
# Set this to the location of the nimbase.h file so
|
||||
# the script can update it if it changes.
|
||||
PATH_TO_NIMBASE=~/project/nimrod/lib/nimbase.h
|
||||
|
||||
# Force errors to fail script.
|
||||
set -e
|
||||
|
||||
# If we are running from inside the scripts subdir, get out.
|
||||
if [ ! -d src ]
|
||||
then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
DEST_NIMBASE=jni/nimcache/nimbase.h
|
||||
|
||||
# Ok, are we out now?
|
||||
if [ -d src ]
|
||||
then
|
||||
$PATH_TO_NIMROD c --noMain --app:lib \
|
||||
--nimcache:jni/nimcache --cpu:arm --os:linux \
|
||||
--compileOnly --header ../nimrod_backend/*.nim
|
||||
if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ]
|
||||
then
|
||||
echo "Updating nimbase.h"
|
||||
cp "${PATH_TO_NIMBASE}" "${DEST_NIMBASE}"
|
||||
fi
|
||||
else
|
||||
echo "Uh oh, src directory not found?"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -d src ]
|
||||
then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ -d src ]
|
||||
then
|
||||
~/bin/objctags -R \
|
||||
jni \
|
||||
src
|
||||
fi
|
||||
@@ -1,80 +0,0 @@
|
||||
package com.github.nimrod.crosscalculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class CrossCalculator extends Activity
|
||||
{
|
||||
private static final String TAG = "CrossCalculator";
|
||||
private TextView result_text;
|
||||
private EditText edit_text_a, edit_text_b;
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.cross_calculator);
|
||||
|
||||
final Button button = (Button)findViewById(R.id.add_button);
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) { addButtonClicked(); } });
|
||||
|
||||
result_text = (TextView)findViewById(R.id.result_text);
|
||||
edit_text_a = (EditText)findViewById(R.id.edit_text_a);
|
||||
edit_text_b = (EditText)findViewById(R.id.edit_text_b);
|
||||
}
|
||||
|
||||
/** Handles clicks on the addition button.
|
||||
* Reads the values form the input fields and performs the calculation.
|
||||
*/
|
||||
private void addButtonClicked()
|
||||
{
|
||||
int a = 0, b = 0;
|
||||
String errors = "";
|
||||
final String a_text = edit_text_a.getText().toString();
|
||||
final String b_text = edit_text_b.getText().toString();
|
||||
try {
|
||||
a = Integer.valueOf(a_text, 10);
|
||||
} catch (NumberFormatException e) {
|
||||
errors += "Can't parse a value '" + a_text + "'. ";
|
||||
}
|
||||
try {
|
||||
b = Integer.valueOf(b_text, 10);
|
||||
} catch (NumberFormatException e) {
|
||||
errors += "Can't parse b value '" + b_text + "'";
|
||||
}
|
||||
final int c = myAdd(a, b);
|
||||
result_text.setText("myAdd(" + a + ", " + b + ") = " + c);
|
||||
|
||||
if (errors.length() > 0) {
|
||||
Log.e(TAG, errors);
|
||||
Toast.makeText(this, errors, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
/* A native method that is implemented by the
|
||||
* 'backend-jni' native library, which is packaged
|
||||
* with this application. Adds to integers.
|
||||
*/
|
||||
public native int myAdd(int a, int b);
|
||||
|
||||
/* A native method used to initialise Nimrod.
|
||||
*/
|
||||
static public native void initNimMain();
|
||||
|
||||
/* this is used to load the 'backend-jni' library on application
|
||||
* startup. The library has already been unpacked into
|
||||
* /data/data/com.github.nimrod.backendjni/lib/libbackend-jni.so at
|
||||
* installation time by the package manager.
|
||||
*/
|
||||
static {
|
||||
System.loadLibrary("backend-jni");
|
||||
initNimMain();
|
||||
}
|
||||
}
|
||||
@@ -1,337 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D531422A15BC8611005EFF20 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422915BC8611005EFF20 /* UIKit.framework */; };
|
||||
D531422C15BC8611005EFF20 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422B15BC8611005EFF20 /* Foundation.framework */; };
|
||||
D531422E15BC8611005EFF20 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422D15BC8611005EFF20 /* CoreGraphics.framework */; };
|
||||
D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424A15BC87B6005EFF20 /* AppDelegate.m */; };
|
||||
D531424E15BC87B6005EFF20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424B15BC87B6005EFF20 /* main.m */; };
|
||||
D531427215BC94B1005EFF20 /* backend.m in Sources */ = {isa = PBXBuildFile; fileRef = D531426F15BC94B1005EFF20 /* backend.m */; };
|
||||
D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* stdlib_system.m */; };
|
||||
D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5B6F94615FA8D4C0084A85B /* NRViewController.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
D531422515BC8611005EFF20 /* cross-calculator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cross-calculator.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D531422915BC8611005EFF20 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
D531422B15BC8611005EFF20 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
D531422D15BC8611005EFF20 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
D531424715BC87A5005EFF20 /* cross-calculator-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "cross-calculator-Info.plist"; path = "resources/plist/cross-calculator-Info.plist"; sourceTree = "<group>"; };
|
||||
D531424915BC87B6005EFF20 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = src/AppDelegate.h; sourceTree = "<group>"; };
|
||||
D531424A15BC87B6005EFF20 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = src/AppDelegate.m; sourceTree = "<group>"; };
|
||||
D531424B15BC87B6005EFF20 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = src/main.m; sourceTree = "<group>"; };
|
||||
D531424C15BC87B6005EFF20 /* cross-calculator-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cross-calculator-Prefix.pch"; path = "src/cross-calculator-Prefix.pch"; sourceTree = "<group>"; };
|
||||
D531426715BC91EF005EFF20 /* tags.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = tags.sh; path = scripts/tags.sh; sourceTree = "<group>"; };
|
||||
D531426815BC91EF005EFF20 /* xcode_prebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = xcode_prebuild.sh; path = scripts/xcode_prebuild.sh; sourceTree = "<group>"; };
|
||||
D531426F15BC94B1005EFF20 /* backend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = backend.m; path = build/nimcache/backend.m; sourceTree = "<group>"; };
|
||||
D531427115BC94B1005EFF20 /* stdlib_system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = stdlib_system.m; path = build/nimcache/stdlib_system.m; sourceTree = "<group>"; };
|
||||
D592E19015C7120F005258EA /* backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = backend.h; path = build/nimcache/backend.h; sourceTree = "<group>"; };
|
||||
D592E19115C71415005258EA /* nimbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nimbase.h; path = build/nimcache/nimbase.h; sourceTree = "<group>"; };
|
||||
D5B6F94515FA8D4C0084A85B /* NRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NRViewController.h; path = src/NRViewController.h; sourceTree = "<group>"; };
|
||||
D5B6F94615FA8D4C0084A85B /* NRViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NRViewController.m; path = src/NRViewController.m; sourceTree = "<group>"; };
|
||||
D5B6F96315FB448D0084A85B /* NRViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = NRViewController.xib; path = resources/ui/NRViewController.xib; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
D531422215BC8610005EFF20 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D531422A15BC8611005EFF20 /* UIKit.framework in Frameworks */,
|
||||
D531422C15BC8611005EFF20 /* Foundation.framework in Frameworks */,
|
||||
D531422E15BC8611005EFF20 /* CoreGraphics.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
D531421A15BC8610005EFF20 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531426A15BC93D5005EFF20 /* build */,
|
||||
D531424515BC874E005EFF20 /* resources */,
|
||||
D531426615BC91E1005EFF20 /* scripts */,
|
||||
D531424815BC87AD005EFF20 /* src */,
|
||||
D531422815BC8611005EFF20 /* Frameworks */,
|
||||
D531422615BC8611005EFF20 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531422615BC8611005EFF20 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531422515BC8611005EFF20 /* cross-calculator.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531422815BC8611005EFF20 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531422915BC8611005EFF20 /* UIKit.framework */,
|
||||
D531422B15BC8611005EFF20 /* Foundation.framework */,
|
||||
D531422D15BC8611005EFF20 /* CoreGraphics.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531424515BC874E005EFF20 /* resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531424615BC8756005EFF20 /* plist */,
|
||||
D5B6F96115FB447C0084A85B /* ui */,
|
||||
);
|
||||
name = resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531424615BC8756005EFF20 /* plist */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531424715BC87A5005EFF20 /* cross-calculator-Info.plist */,
|
||||
);
|
||||
name = plist;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531424815BC87AD005EFF20 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531424915BC87B6005EFF20 /* AppDelegate.h */,
|
||||
D531424A15BC87B6005EFF20 /* AppDelegate.m */,
|
||||
D531424C15BC87B6005EFF20 /* cross-calculator-Prefix.pch */,
|
||||
D531424B15BC87B6005EFF20 /* main.m */,
|
||||
D5B6F94515FA8D4C0084A85B /* NRViewController.h */,
|
||||
D5B6F94615FA8D4C0084A85B /* NRViewController.m */,
|
||||
);
|
||||
name = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531426615BC91E1005EFF20 /* scripts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531426715BC91EF005EFF20 /* tags.sh */,
|
||||
D531426815BC91EF005EFF20 /* xcode_prebuild.sh */,
|
||||
);
|
||||
name = scripts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531426A15BC93D5005EFF20 /* build */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D531426E15BC94A6005EFF20 /* nimrod */,
|
||||
);
|
||||
name = build;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D531426E15BC94A6005EFF20 /* nimrod */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D592E19015C7120F005258EA /* backend.h */,
|
||||
D531426F15BC94B1005EFF20 /* backend.m */,
|
||||
D592E19115C71415005258EA /* nimbase.h */,
|
||||
D531427115BC94B1005EFF20 /* stdlib_system.m */,
|
||||
);
|
||||
name = nimrod;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D5B6F96115FB447C0084A85B /* ui */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D5B6F96315FB448D0084A85B /* NRViewController.xib */,
|
||||
);
|
||||
name = ui;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
D531422415BC8610005EFF20 /* cross-calculator */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D531423D15BC8611005EFF20 /* Build configuration list for PBXNativeTarget "cross-calculator" */;
|
||||
buildPhases = (
|
||||
D531426915BC926C005EFF20 /* ShellScript */,
|
||||
D531422115BC8610005EFF20 /* Sources */,
|
||||
D531422215BC8610005EFF20 /* Frameworks */,
|
||||
D531422315BC8610005EFF20 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "cross-calculator";
|
||||
productName = "cross-calculator";
|
||||
productReference = D531422515BC8611005EFF20 /* cross-calculator.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
D531421C15BC8610005EFF20 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0420;
|
||||
ORGANIZATIONNAME = "Electric Hands Software";
|
||||
};
|
||||
buildConfigurationList = D531421F15BC8610005EFF20 /* Build configuration list for PBXProject "cross-calculator" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = D531421A15BC8610005EFF20;
|
||||
productRefGroup = D531422615BC8611005EFF20 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
D531422415BC8610005EFF20 /* cross-calculator */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
D531422315BC8610005EFF20 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
D531426915BC926C005EFF20 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = scripts/xcode_prebuild.sh;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
D531422115BC8610005EFF20 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */,
|
||||
D531424E15BC87B6005EFF20 /* main.m in Sources */,
|
||||
D531427215BC94B1005EFF20 /* backend.m in Sources */,
|
||||
D531427415BC94B1005EFF20 /* stdlib_system.m in Sources */,
|
||||
D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D531423B15BC8611005EFF20 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = (
|
||||
armv7,
|
||||
armv6,
|
||||
);
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = "";
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D531423C15BC8611005EFF20 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = (
|
||||
armv7,
|
||||
armv6,
|
||||
);
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_VERSION = "";
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
|
||||
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D531423E15BC8611005EFF20 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "src/cross-calculator-Prefix.pch";
|
||||
INFOPLIST_FILE = "resources/plist/cross-calculator-Info.plist";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D531423F15BC8611005EFF20 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "src/cross-calculator-Prefix.pch";
|
||||
INFOPLIST_FILE = "resources/plist/cross-calculator-Info.plist";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
D531421F15BC8610005EFF20 /* Build configuration list for PBXProject "cross-calculator" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D531423B15BC8611005EFF20 /* Debug */,
|
||||
D531423C15BC8611005EFF20 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D531423D15BC8611005EFF20 /* Build configuration list for PBXNativeTarget "cross-calculator" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D531423E15BC8611005EFF20 /* Debug */,
|
||||
D531423F15BC8611005EFF20 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = D531421C15BC8610005EFF20 /* Project object */;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
In this directory you will find the iOS platform cross-calculator sample.
|
||||
|
||||
The iOS version of the code builds a view controller in charge of displaying
|
||||
the interface to the user. The Nim backend code is compiled into C code and
|
||||
put into build/nimrod as a pre-build phase of the project.
|
||||
|
||||
When the calculate button is used the view controller calls the Nim code to
|
||||
delegate the logic of the operation and puts the result in a label for display.
|
||||
All interface error checks are implemented in the view controller.
|
||||
|
||||
This version of the iOS project is known to work with Xcode 4.2 and Xcode
|
||||
4.4.1. The final binary can be deployed on iOS 3.x to 5.x supporting all iOS
|
||||
platforms and versions available at the moment.
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFiles</key>
|
||||
<array/>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.github.nimrod.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>UIApplicationExitsOnSuspend</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,479 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
|
||||
<data>
|
||||
<int key="IBDocument.SystemTarget">0</int>
|
||||
<string key="IBDocument.SystemVersion">11E53</string>
|
||||
<string key="IBDocument.InterfaceBuilderVersion">2549</string>
|
||||
<string key="IBDocument.AppKitVersion">1138.47</string>
|
||||
<string key="IBDocument.HIToolboxVersion">569.00</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="NS.object.0">1498</string>
|
||||
</object>
|
||||
<array key="IBDocument.IntegratedClassDependencies">
|
||||
<string>IBProxyObject</string>
|
||||
<string>IBUIButton</string>
|
||||
<string>IBUILabel</string>
|
||||
<string>IBUITextField</string>
|
||||
<string>IBUIView</string>
|
||||
</array>
|
||||
<array key="IBDocument.PluginDependencies">
|
||||
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</array>
|
||||
<object class="NSMutableDictionary" key="IBDocument.Metadata">
|
||||
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
|
||||
<integer value="1" key="NS.object.0"/>
|
||||
</object>
|
||||
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
|
||||
<object class="IBProxyObject" id="372490531">
|
||||
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBProxyObject" id="975951072">
|
||||
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<object class="IBUIView" id="191373211">
|
||||
<reference key="NSNextResponder"/>
|
||||
<int key="NSvFlags">274</int>
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="IBUIButton" id="467453084">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{0, -10}, {320, 480}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<int key="IBUITag">1</int>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<object class="NSColor" key="IBUIHighlightedTitleColor" id="95215378">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<object class="NSColor" key="IBUINormalTitleShadowColor" id="1056499111">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MC41AA</bytes>
|
||||
</object>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription" id="686052398">
|
||||
<int key="type">2</int>
|
||||
<double key="pointSize">15</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont" id="594372787">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">15</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUILabel" id="353054360">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">306</int>
|
||||
<string key="NSFrameSize">{320, 34}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="525225214"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<int key="IBUITag">2</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Nim Crossplatform Calculator</string>
|
||||
<object class="NSColor" key="IBUITextColor" id="128895179">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MCAwIDAAA</bytes>
|
||||
</object>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">0</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<int key="IBUITextAlignment">1</int>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription">
|
||||
<int key="type">2</int>
|
||||
<double key="pointSize">18</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont">
|
||||
<string key="NSName">Helvetica-Bold</string>
|
||||
<double key="NSSize">18</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUILabel" id="525225214">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">294</int>
|
||||
<string key="NSFrame">{{20, 42}, {165, 31}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="1040444341"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<int key="IBUITag">3</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Value A:</string>
|
||||
<reference key="IBUITextColor" ref="128895179"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">0</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription" id="768572949">
|
||||
<int key="type">1</int>
|
||||
<double key="pointSize">17</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont" id="972319481">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">17</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUILabel" id="904781109">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">294</int>
|
||||
<string key="NSFrame">{{20, 81}, {165, 31}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="1041721572"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<int key="IBUITag">4</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Value B:</string>
|
||||
<reference key="IBUITextColor" ref="128895179"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">0</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<reference key="IBUIFontDescription" ref="768572949"/>
|
||||
<reference key="IBUIFont" ref="972319481"/>
|
||||
</object>
|
||||
<object class="IBUIButton" id="557594991">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">291</int>
|
||||
<string key="NSFrame">{{193, 124}, {107, 37}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<int key="IBUITag">5</int>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentHorizontalAlignment">0</int>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<int key="IBUIButtonType">1</int>
|
||||
<string key="IBUINormalTitle">Add!</string>
|
||||
<reference key="IBUIHighlightedTitleColor" ref="95215378"/>
|
||||
<object class="NSColor" key="IBUINormalTitleColor">
|
||||
<int key="NSColorSpace">1</int>
|
||||
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
|
||||
</object>
|
||||
<reference key="IBUINormalTitleShadowColor" ref="1056499111"/>
|
||||
<reference key="IBUIFontDescription" ref="686052398"/>
|
||||
<reference key="IBUIFont" ref="594372787"/>
|
||||
</object>
|
||||
<object class="IBUILabel" id="360864196">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">292</int>
|
||||
<string key="NSFrame">{{20, 124}, {60, 37}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="521073831"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<int key="IBUITag">6</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText">Result:</string>
|
||||
<reference key="IBUITextColor" ref="128895179"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">0</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<reference key="IBUIFontDescription" ref="768572949"/>
|
||||
<reference key="IBUIFont" ref="972319481"/>
|
||||
</object>
|
||||
<object class="IBUILabel" id="521073831">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">294</int>
|
||||
<string key="NSFrame">{{88, 124}, {97, 37}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="557594991"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUIContentMode">7</int>
|
||||
<int key="IBUITag">7</int>
|
||||
<bool key="IBUIUserInteractionEnabled">NO</bool>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<string key="IBUIText"/>
|
||||
<reference key="IBUITextColor" ref="128895179"/>
|
||||
<nil key="IBUIHighlightedColor"/>
|
||||
<int key="IBUIBaselineAdjustment">0</int>
|
||||
<float key="IBUIMinimumFontSize">10</float>
|
||||
<reference key="IBUIFontDescription" ref="768572949"/>
|
||||
<reference key="IBUIFont" ref="972319481"/>
|
||||
</object>
|
||||
<object class="IBUITextField" id="1040444341">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">291</int>
|
||||
<string key="NSFrame">{{193, 42}, {107, 31}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="904781109"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUITag">8</int>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<string key="IBUIText"/>
|
||||
<int key="IBUIBorderStyle">3</int>
|
||||
<string key="IBUIPlaceholder">Integer</string>
|
||||
<object class="NSColor" key="IBUITextColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MAA</bytes>
|
||||
<object class="NSColorSpace" key="NSCustomColorSpace" id="433120901">
|
||||
<int key="NSID">2</int>
|
||||
</object>
|
||||
</object>
|
||||
<int key="IBUITextAlignment">1</int>
|
||||
<bool key="IBUIAdjustsFontSizeToFit">YES</bool>
|
||||
<float key="IBUIMinimumFontSize">17</float>
|
||||
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
|
||||
<int key="IBUIKeyboardType">4</int>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<int key="IBUIClearButtonMode">1</int>
|
||||
<object class="IBUIFontDescription" key="IBUIFontDescription" id="836805198">
|
||||
<int key="type">1</int>
|
||||
<double key="pointSize">14</double>
|
||||
</object>
|
||||
<object class="NSFont" key="IBUIFont" id="700927782">
|
||||
<string key="NSName">Helvetica</string>
|
||||
<double key="NSSize">14</double>
|
||||
<int key="NSfFlags">16</int>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBUITextField" id="1041721572">
|
||||
<reference key="NSNextResponder" ref="191373211"/>
|
||||
<int key="NSvFlags">291</int>
|
||||
<string key="NSFrame">{{193, 81}, {107, 31}}</string>
|
||||
<reference key="NSSuperview" ref="191373211"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="360864196"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="IBUIOpaque">NO</bool>
|
||||
<bool key="IBUIClipsSubviews">YES</bool>
|
||||
<int key="IBUITag">9</int>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<int key="IBUIContentVerticalAlignment">0</int>
|
||||
<string key="IBUIText"/>
|
||||
<int key="IBUIBorderStyle">3</int>
|
||||
<string key="IBUIPlaceholder">Integer</string>
|
||||
<object class="NSColor" key="IBUITextColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MAA</bytes>
|
||||
<reference key="NSCustomColorSpace" ref="433120901"/>
|
||||
</object>
|
||||
<int key="IBUITextAlignment">1</int>
|
||||
<bool key="IBUIAdjustsFontSizeToFit">YES</bool>
|
||||
<float key="IBUIMinimumFontSize">17</float>
|
||||
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
|
||||
<int key="IBUIKeyboardType">4</int>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
<int key="IBUIClearButtonMode">1</int>
|
||||
<reference key="IBUIFontDescription" ref="836805198"/>
|
||||
<reference key="IBUIFont" ref="700927782"/>
|
||||
</object>
|
||||
</array>
|
||||
<string key="NSFrame">{{0, 20}, {320, 460}}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="353054360"/>
|
||||
<object class="NSColor" key="IBUIBackgroundColor">
|
||||
<int key="NSColorSpace">3</int>
|
||||
<bytes key="NSWhite">MQA</bytes>
|
||||
<reference key="NSCustomColorSpace" ref="433120901"/>
|
||||
</object>
|
||||
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
|
||||
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
</object>
|
||||
</array>
|
||||
<object class="IBObjectContainer" key="IBDocument.Objects">
|
||||
<array class="NSMutableArray" key="connectionRecords"/>
|
||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||
<array key="orderedObjects">
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">0</int>
|
||||
<array key="object" id="0"/>
|
||||
<reference key="children" ref="1000"/>
|
||||
<nil key="parent"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">1</int>
|
||||
<reference key="object" ref="191373211"/>
|
||||
<array class="NSMutableArray" key="children">
|
||||
<reference ref="353054360"/>
|
||||
<reference ref="525225214"/>
|
||||
<reference ref="904781109"/>
|
||||
<reference ref="557594991"/>
|
||||
<reference ref="360864196"/>
|
||||
<reference ref="521073831"/>
|
||||
<reference ref="1040444341"/>
|
||||
<reference ref="1041721572"/>
|
||||
<reference ref="467453084"/>
|
||||
</array>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-1</int>
|
||||
<reference key="object" ref="372490531"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
<string key="objectName">File's Owner</string>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">-2</int>
|
||||
<reference key="object" ref="975951072"/>
|
||||
<reference key="parent" ref="0"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">14</int>
|
||||
<reference key="object" ref="1041721572"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">13</int>
|
||||
<reference key="object" ref="1040444341"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">12</int>
|
||||
<reference key="object" ref="521073831"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">11</int>
|
||||
<reference key="object" ref="360864196"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">10</int>
|
||||
<reference key="object" ref="557594991"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">8</int>
|
||||
<reference key="object" ref="904781109"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">7</int>
|
||||
<reference key="object" ref="525225214"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">4</int>
|
||||
<reference key="object" ref="353054360"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
<object class="IBObjectRecord">
|
||||
<int key="objectID">22</int>
|
||||
<reference key="object" ref="467453084"/>
|
||||
<reference key="parent" ref="191373211"/>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||
<string key="-1.CustomClassName">NRViewController</string>
|
||||
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="-2.CustomClassName">UIResponder</string>
|
||||
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="11.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="13.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">22</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NRViewController</string>
|
||||
<string key="superclassName">UIViewController</string>
|
||||
<dictionary class="NSMutableDictionary" key="actions">
|
||||
<string key="backgroundTouched">id</string>
|
||||
<string key="calculateButtonTouched">id</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="actionInfosByName">
|
||||
<object class="IBActionInfo" key="backgroundTouched">
|
||||
<string key="name">backgroundTouched</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
<object class="IBActionInfo" key="calculateButtonTouched">
|
||||
<string key="name">calculateButtonTouched</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="outlets">
|
||||
<string key="aText">UITextField</string>
|
||||
<string key="bText">UITextField</string>
|
||||
<string key="calculateButton">UIButton</string>
|
||||
<string key="resultLabel">UILabel</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<object class="IBToOneOutletInfo" key="aText">
|
||||
<string key="name">aText</string>
|
||||
<string key="candidateClassName">UITextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="bText">
|
||||
<string key="name">bText</string>
|
||||
<string key="candidateClassName">UITextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="calculateButton">
|
||||
<string key="name">calculateButton</string>
|
||||
<string key="candidateClassName">UIButton</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="resultLabel">
|
||||
<string key="name">resultLabel</string>
|
||||
<string key="candidateClassName">UILabel</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/NRViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
</object>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
|
||||
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
|
||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
|
||||
<real value="0.0" key="NS.object.0"/>
|
||||
</object>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<string key="IBCocoaTouchPluginVersion">1498</string>
|
||||
</data>
|
||||
</archive>
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -d src ]
|
||||
then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ -d src ]
|
||||
then
|
||||
~/bin/objctags -R \
|
||||
build/nimcache \
|
||||
src
|
||||
fi
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Set this to the full path of your nimrod compiler
|
||||
# since Xcode doesn't inherit your user environment.
|
||||
PATH_TO_NIMROD=~/project/nimrod/bin/nimrod
|
||||
# Set this to the location of the nimbase.h file so
|
||||
# the script can update it if it changes.
|
||||
PATH_TO_NIMBASE=~/project/nimrod/lib/nimbase.h
|
||||
|
||||
# Force errors to fail script.
|
||||
set -e
|
||||
|
||||
# If we are running from inside the scripts subdir, get out.
|
||||
if [ ! -d src ]
|
||||
then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
DEST_NIMBASE=build/nimcache/nimbase.h
|
||||
|
||||
# Ok, are we out now?
|
||||
if [ -d src ]
|
||||
then
|
||||
$PATH_TO_NIMROD objc --noMain --app:lib \
|
||||
--nimcache:./build/nimcache --compileOnly \
|
||||
--header --cpu:i386 ../nimrod_backend/backend.nim
|
||||
if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ]
|
||||
then
|
||||
echo "Updating nimbase.h"
|
||||
cp "${PATH_TO_NIMBASE}" "${DEST_NIMBASE}"
|
||||
fi
|
||||
else
|
||||
echo "Uh oh, src directory not found?"
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,7 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
@@ -1,39 +0,0 @@
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "NRViewController.h"
|
||||
|
||||
|
||||
@interface AppDelegate ()
|
||||
@property (nonatomic, retain) NRViewController *viewController;
|
||||
@end
|
||||
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
@synthesize viewController = _viewController;
|
||||
@synthesize window = _window;
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
self.window = [[[UIWindow alloc]
|
||||
initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
|
||||
|
||||
self.viewController = [[NRViewController new] autorelease];
|
||||
if ([self.window respondsToSelector:@selector(setRootViewController:)])
|
||||
self.window.rootViewController = self.viewController;
|
||||
else
|
||||
[self.window addSubview:self.viewController.view];
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_window release];
|
||||
[_viewController release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,11 +0,0 @@
|
||||
@interface NRViewController : UIViewController
|
||||
|
||||
@property (nonatomic, retain) IBOutlet UIButton *calculateButton;
|
||||
@property (nonatomic, retain) IBOutlet UITextField *aText;
|
||||
@property (nonatomic, retain) IBOutlet UITextField *bText;
|
||||
@property (nonatomic, retain) IBOutlet UILabel *resultLabel;
|
||||
|
||||
- (IBAction)calculateButtonTouched;
|
||||
- (IBAction)backgroundTouched;
|
||||
|
||||
@end
|
||||
@@ -1,210 +0,0 @@
|
||||
#import "NRViewController.h"
|
||||
|
||||
#import "backend.h"
|
||||
|
||||
|
||||
@implementation NRViewController
|
||||
|
||||
@synthesize aText = _aText;
|
||||
@synthesize bText = _bText;
|
||||
@synthesize calculateButton = _calculateButton;
|
||||
@synthesize resultLabel = _resultLabel;
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_aText release];
|
||||
[_bText release];
|
||||
[_calculateButton release];
|
||||
[_resultLabel release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)viewDidUnload
|
||||
{
|
||||
self.calculateButton = nil;
|
||||
self.aText = nil;
|
||||
self.bText = nil;
|
||||
self.resultLabel = nil;
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:
|
||||
(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
/// User wants to calculate the inputs. Well, do it!
|
||||
- (IBAction)calculateButtonTouched
|
||||
{
|
||||
// Dismiss all keyboards.
|
||||
[self backgroundTouched];
|
||||
|
||||
// Call Nim code, store the result and display it.
|
||||
const int a = [self.aText.text intValue];
|
||||
const int b = [self.bText.text intValue];
|
||||
const int c = myAdd(a, b);
|
||||
self.resultLabel.text = [NSString stringWithFormat:@"%d + %d = %d",
|
||||
a, b, c];
|
||||
}
|
||||
|
||||
/// If the user touches the background, dismiss any visible keyboard.
|
||||
- (IBAction)backgroundTouched
|
||||
{
|
||||
[self.aText resignFirstResponder];
|
||||
[self.bText resignFirstResponder];
|
||||
}
|
||||
|
||||
/** Custom loadView method for backwards compatibility.
|
||||
* Unfortunately I've been unable to coerce Xcode 4.4 to generate nib files
|
||||
* which are compatible with my trusty iOS 3.0 ipod touch so in order to be
|
||||
* fully compatible for all devices we have to build the interface manually in
|
||||
* code rather than through the keyed archivers provided by the interface
|
||||
* builder.
|
||||
*
|
||||
* Rather than recreating the user interface manually in code the tool nib2obj
|
||||
* was used on the xib file and slightly modified to fit the original property
|
||||
* names. Which means here is a lot of garbage you would never write in real
|
||||
* life. Please ignore the following "wall of code" for the purposes of
|
||||
* learning Nim, this is all just because Apple can't be bothered to
|
||||
* maintain backwards compatibility properly.
|
||||
*/
|
||||
- (void)loadView
|
||||
{
|
||||
[super loadView];
|
||||
|
||||
self.calculateButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
self.calculateButton.autoresizesSubviews = YES;
|
||||
self.calculateButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.calculateButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
|
||||
self.calculateButton.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
self.calculateButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
|
||||
self.calculateButton.frame = CGRectMake(193.0, 124.0, 107.0, 37.0);
|
||||
self.calculateButton.tag = 5;
|
||||
[self.calculateButton setTitle:@"Add!" forState:UIControlStateNormal];
|
||||
[self.calculateButton addTarget:self
|
||||
action:@selector(calculateButtonTouched)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
UILabel *label11 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 124.0, 60.0, 37.0)];
|
||||
label11.adjustsFontSizeToFitWidth = YES;
|
||||
label11.autoresizesSubviews = YES;
|
||||
label11.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
label11.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
label11.frame = CGRectMake(20.0, 124.0, 60.0, 37.0);
|
||||
label11.tag = 6;
|
||||
label11.text = @"Result:";
|
||||
|
||||
UILabel *label4 = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 34.0)];
|
||||
label4.adjustsFontSizeToFitWidth = YES;
|
||||
label4.autoresizesSubviews = YES;
|
||||
label4.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
|
||||
label4.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
label4.frame = CGRectMake(0.0, 0.0, 320.0, 34.0);
|
||||
label4.tag = 2;
|
||||
label4.text = @"Nim Crossplatform Calculator";
|
||||
label4.textAlignment = UITextAlignmentCenter;
|
||||
|
||||
UIButton *background_button = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
background_button.autoresizesSubviews = YES;
|
||||
background_button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
background_button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
|
||||
background_button.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
background_button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
|
||||
background_button.frame = CGRectMake(0.0, -10.0, 320.0, 480.0);
|
||||
background_button.tag = 1;
|
||||
[background_button addTarget:self action:@selector(backgroundTouched)
|
||||
forControlEvents:UIControlEventTouchDown];
|
||||
|
||||
self.resultLabel = [[[UILabel alloc] initWithFrame:CGRectMake(88.0, 124.0, 97.0, 37.0)] autorelease];
|
||||
self.resultLabel.adjustsFontSizeToFitWidth = YES;
|
||||
self.resultLabel.autoresizesSubviews = YES;
|
||||
self.resultLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.resultLabel.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
self.resultLabel.frame = CGRectMake(88.0, 124.0, 97.0, 37.0);
|
||||
self.resultLabel.tag = 7;
|
||||
self.resultLabel.text = @"";
|
||||
|
||||
self.aText = [[[UITextField alloc] initWithFrame:CGRectMake(193.0, 42.0, 107.0, 31.0)] autorelease];
|
||||
self.aText.adjustsFontSizeToFitWidth = YES;
|
||||
self.aText.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
self.aText.autocorrectionType = UITextAutocorrectionTypeDefault;
|
||||
self.aText.autoresizesSubviews = YES;
|
||||
self.aText.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.aText.borderStyle = UITextBorderStyleRoundedRect;
|
||||
self.aText.clearButtonMode = UITextFieldViewModeWhileEditing;
|
||||
self.aText.clearsOnBeginEditing = NO;
|
||||
self.aText.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
self.aText.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
self.aText.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
|
||||
self.aText.enablesReturnKeyAutomatically = NO;
|
||||
self.aText.frame = CGRectMake(193.0, 42.0, 107.0, 31.0);
|
||||
self.aText.keyboardAppearance = UIKeyboardAppearanceDefault;
|
||||
self.aText.keyboardType = UIKeyboardTypeNumberPad;
|
||||
self.aText.placeholder = @"Integer";
|
||||
self.aText.returnKeyType = UIReturnKeyDefault;
|
||||
self.aText.tag = 8;
|
||||
self.aText.text = @"";
|
||||
self.aText.textAlignment = UITextAlignmentCenter;
|
||||
|
||||
UILabel *label7 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 42.0, 165.0, 31.0)];
|
||||
label7.adjustsFontSizeToFitWidth = YES;
|
||||
label7.autoresizesSubviews = YES;
|
||||
label7.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
label7.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
label7.frame = CGRectMake(20.0, 42.0, 165.0, 31.0);
|
||||
label7.tag = 3;
|
||||
label7.text = @"Value A:";
|
||||
|
||||
UILabel *label8 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 81.0, 165.0, 31.0)];
|
||||
label8.adjustsFontSizeToFitWidth = YES;
|
||||
label8.autoresizesSubviews = YES;
|
||||
label8.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
label8.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
label8.frame = CGRectMake(20.0, 81.0, 165.0, 31.0);
|
||||
label8.tag = 4;
|
||||
label8.text = @"Value B:";
|
||||
|
||||
self.bText = [[[UITextField alloc]
|
||||
initWithFrame:CGRectMake(193.0, 81.0, 107.0, 31.0)] autorelease];
|
||||
self.bText.adjustsFontSizeToFitWidth = YES;
|
||||
self.bText.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
self.bText.autocorrectionType = UITextAutocorrectionTypeDefault;
|
||||
self.bText.autoresizesSubviews = YES;
|
||||
self.bText.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.bText.borderStyle = UITextBorderStyleRoundedRect;
|
||||
self.bText.clearButtonMode = UITextFieldViewModeWhileEditing;
|
||||
self.bText.clearsOnBeginEditing = NO;
|
||||
self.bText.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
self.bText.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
self.bText.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
|
||||
self.bText.enablesReturnKeyAutomatically = NO;
|
||||
self.bText.frame = CGRectMake(193.0, 81.0, 107.0, 31.0);
|
||||
self.bText.keyboardAppearance = UIKeyboardAppearanceDefault;
|
||||
self.bText.keyboardType = UIKeyboardTypeNumberPad;
|
||||
self.bText.placeholder = @"Integer";
|
||||
self.bText.returnKeyType = UIReturnKeyDefault;
|
||||
self.bText.tag = 9;
|
||||
self.bText.text = @"";
|
||||
self.bText.textAlignment = UITextAlignmentCenter;
|
||||
|
||||
self.view.frame = CGRectMake(0.0, 20.0, 320.0, 460.0);
|
||||
self.view.autoresizesSubviews = YES;
|
||||
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.view.backgroundColor = [UIColor colorWithWhite:1.000 alpha:1.000];
|
||||
self.view.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
|
||||
self.view.frame = CGRectMake(0.0, 20.0, 320.0, 460.0);
|
||||
self.view.tag = 0;
|
||||
|
||||
[self.view addSubview:background_button];
|
||||
[self.view addSubview:label4];
|
||||
[self.view addSubview:label7];
|
||||
[self.view addSubview:label8];
|
||||
[self.view addSubview:self.calculateButton];
|
||||
[self.view addSubview:label11];
|
||||
[self.view addSubview:self.resultLabel];
|
||||
[self.view addSubview:self.aText];
|
||||
[self.view addSubview:self.bText];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,10 +0,0 @@
|
||||
#import <Availability.h>
|
||||
|
||||
#ifndef __IPHONE_3_0
|
||||
#warning "This project uses features only available in iOS SDK 3.0 and later."
|
||||
#endif
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "backend.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
NimMain();
|
||||
return UIApplicationMain(argc, argv, nil,
|
||||
NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="7"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<LRSInOutputDirectory Value="False"/>
|
||||
</Flags>
|
||||
<MainUnit Value="0"/>
|
||||
<TargetFileExt Value=".exe"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
<ActiveEditorIndexAtStart Value="1"/>
|
||||
</General>
|
||||
<VersionInfo>
|
||||
<ProjectVersion Value=""/>
|
||||
<Language Value=""/>
|
||||
<CharSet Value=""/>
|
||||
</VersionInfo>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IgnoreBinaries Value="False"/>
|
||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<local>
|
||||
<FormatVersion Value="1"/>
|
||||
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="1">
|
||||
<Item1>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item1>
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
<Filename Value="nimlaz.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="nimlaz"/>
|
||||
<CursorPos X="17" Y="21"/>
|
||||
<TopLine Value="1"/>
|
||||
<EditorIndex Value="1"/>
|
||||
<UsageCount Value="21"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="Form1"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="Unit1"/>
|
||||
<CursorPos X="26" Y="27"/>
|
||||
<TopLine Value="2"/>
|
||||
<EditorIndex Value="0"/>
|
||||
<UsageCount Value="21"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit1>
|
||||
</Units>
|
||||
<JumpHistory Count="12" HistoryIndex="11">
|
||||
<Position1>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="27" Column="1" TopLine="1"/>
|
||||
</Position1>
|
||||
<Position2>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="15" Column="3" TopLine="1"/>
|
||||
</Position2>
|
||||
<Position3>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="17" Column="26" TopLine="1"/>
|
||||
</Position3>
|
||||
<Position4>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="16" Column="18" TopLine="1"/>
|
||||
</Position4>
|
||||
<Position5>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="20" Column="43" TopLine="2"/>
|
||||
</Position5>
|
||||
<Position6>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="21" Column="48" TopLine="16"/>
|
||||
</Position6>
|
||||
<Position7>
|
||||
<Filename Value="nimlaz.lpr"/>
|
||||
<Caret Line="1" Column="1" TopLine="1"/>
|
||||
</Position7>
|
||||
<Position8>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="52" Column="17" TopLine="9"/>
|
||||
</Position8>
|
||||
<Position9>
|
||||
<Filename Value="unit1.pas"/>
|
||||
<Caret Line="51" Column="12" TopLine="9"/>
|
||||
</Position9>
|
||||
<Position10>
|
||||
<Filename Value="nimlaz.lpr"/>
|
||||
<Caret Line="21" Column="3" TopLine="1"/>
|
||||
</Position10>
|
||||
<Position11>
|
||||
<Filename Value="nimlaz.lpr"/>
|
||||
<Caret Line="20" Column="1" TopLine="1"/>
|
||||
</Position11>
|
||||
<Position12>
|
||||
<Filename Value="nimlaz.lpr"/>
|
||||
<Caret Line="21" Column="7" TopLine="1"/>
|
||||
</Position12>
|
||||
</JumpHistory>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="8"/>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)/"/>
|
||||
</SearchPaths>
|
||||
<Linking>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item3>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
||||
@@ -1,21 +0,0 @@
|
||||
program nimlaz;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms
|
||||
{ you can add units after this }, Unit1, LResources;
|
||||
|
||||
{$IFDEF WINDOWS}{$R nimlaz.rc}{$ENDIF}
|
||||
|
||||
begin
|
||||
{$I nimlaz.lrs}
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TForm1, Form1);
|
||||
Application.Run;
|
||||
end.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
#define RT_MANIFEST 24
|
||||
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
|
||||
#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2
|
||||
#define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3
|
||||
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "nimlaz.manifest"
|
||||
@@ -1,8 +0,0 @@
|
||||
This example demonstrates how to use Nim with Lazarus. The GUI is generated
|
||||
with Lazarus, while the "backend" is written in Nim. To compile the example,
|
||||
use this command:
|
||||
|
||||
nim c --app:gui --no_main --no_linking backend.nim
|
||||
|
||||
Open the ``nimlaz.lpi`` file in Lazarus and run the program.
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
object Form1: TForm1
|
||||
Left = 553
|
||||
Height = 111
|
||||
Top = 464
|
||||
Width = 448
|
||||
ActiveControl = SpinEdit1
|
||||
Caption = 'Sum'
|
||||
ClientHeight = 111
|
||||
ClientWidth = 448
|
||||
OnCreate = FormCreate
|
||||
LCLVersion = '0.9.28.2'
|
||||
object Label1: TLabel
|
||||
Left = 8
|
||||
Height = 18
|
||||
Top = 72
|
||||
Width = 34
|
||||
Caption = 'Sum:'
|
||||
ParentColor = False
|
||||
end
|
||||
object SpinEdit1: TSpinEdit
|
||||
Left = 8
|
||||
Height = 27
|
||||
Top = 8
|
||||
Width = 436
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
OnChange = SpinEdit1Change
|
||||
TabOrder = 0
|
||||
end
|
||||
object SpinEdit2: TSpinEdit
|
||||
Left = 8
|
||||
Height = 27
|
||||
Top = 40
|
||||
Width = 436
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
OnChange = SpinEdit1Change
|
||||
TabOrder = 1
|
||||
end
|
||||
object Edit1: TEdit
|
||||
Left = 48
|
||||
Height = 27
|
||||
Top = 72
|
||||
Width = 396
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
TabOrder = 2
|
||||
end
|
||||
end
|
||||
@@ -1,58 +0,0 @@
|
||||
unit Unit1;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
|
||||
Spin, StdCtrls;
|
||||
|
||||
type
|
||||
|
||||
{ TForm1 }
|
||||
|
||||
TForm1 = class(TForm)
|
||||
Edit1: TEdit;
|
||||
Label1: TLabel;
|
||||
SpinEdit1: TSpinEdit;
|
||||
SpinEdit2: TSpinEdit;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure SpinEdit1Change(Sender: TObject);
|
||||
private
|
||||
{ private declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
Form1: TForm1;
|
||||
|
||||
implementation
|
||||
|
||||
{ TForm1 }
|
||||
|
||||
{$link nimcache/lib/system.o}
|
||||
{$link nimcache/backend.o}
|
||||
{$link nimcache/nim__dat.o}
|
||||
{$linklib c}
|
||||
|
||||
procedure NimMain; cdecl; external;
|
||||
function myAdd(x, y: longint): longint; cdecl; external;
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
begin
|
||||
// we initialize the Nim data structures here:
|
||||
NimMain();
|
||||
end;
|
||||
|
||||
procedure TForm1.SpinEdit1Change(Sender: TObject);
|
||||
begin
|
||||
Edit1.text := IntToStr(myAdd(SpinEdit1.Value, SpinEdit2.Value));
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$I unit1.lrs}
|
||||
|
||||
end.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Backend for the different user interfaces.
|
||||
|
||||
proc myAdd*(x, y: int): int {.cdecl, exportc.} =
|
||||
result = x + y
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Nim configuration file.
|
||||
# The file is used only to add the path of the backend to the compiler options.
|
||||
|
||||
path="../nim_backend"
|
||||
@@ -1,109 +0,0 @@
|
||||
# Implements a command line interface against the backend.
|
||||
|
||||
import backend, parseopt, strutils
|
||||
|
||||
const
|
||||
USAGE = """nimcalculator - Nim cross platform calculator
|
||||
(beta version, only integer addition is supported!)
|
||||
|
||||
Usage:
|
||||
nimcalculator [options] [-a=value -b=value]
|
||||
Options:
|
||||
-a=value sets the integer value of the a parameter
|
||||
-b=value sets the integer value of the b parameter
|
||||
-h, --help shows this help
|
||||
|
||||
If no options are used, an interactive mode is entered.
|
||||
"""
|
||||
|
||||
type
|
||||
TCommand = enum # The possible types of operation
|
||||
cmdParams, # Two valid parameters were provided
|
||||
cmdInteractive # No parameters were provided, run interactive mode
|
||||
|
||||
TParamConfig = object of RootObj
|
||||
action: TCommand # store the type of operation
|
||||
paramA, paramB: int # possibly store the valid parameters
|
||||
|
||||
|
||||
proc parseCmdLine(): TParamConfig =
|
||||
## Parses the commandline.
|
||||
##
|
||||
## Returns a TParamConfig structure filled with the proper values or directly
|
||||
## calls quit() with the appropriate error message.
|
||||
var
|
||||
hasA = false
|
||||
hasB = false
|
||||
p = initOptParser()
|
||||
key, val: TaintedString
|
||||
|
||||
result.action = cmdInteractive # By default presume interactive mode.
|
||||
try:
|
||||
while true:
|
||||
next p
|
||||
key = p.key
|
||||
val = p.val
|
||||
|
||||
case p.kind
|
||||
of cmdArgument:
|
||||
stdout.write USAGE
|
||||
quit "Erroneous argument detected: " & key, 1
|
||||
of cmdLongOption, cmdShortOption:
|
||||
case key.normalize
|
||||
of "help", "h":
|
||||
stdout.write USAGE
|
||||
quit 0
|
||||
of "a":
|
||||
result.paramA = val.parseInt
|
||||
hasA = true
|
||||
of "b":
|
||||
result.paramB = val.parseInt
|
||||
hasB = true
|
||||
else:
|
||||
stdout.write USAGE
|
||||
quit "Unexpected option: " & key, 2
|
||||
of cmdEnd: break
|
||||
except ValueError:
|
||||
stdout.write USAGE
|
||||
quit "Invalid value " & val & " for parameter " & key, 3
|
||||
|
||||
if hasA and hasB:
|
||||
result.action = cmdParams
|
||||
elif hasA or hasB:
|
||||
stdout.write USAGE
|
||||
quit "Error: provide both A and B to operate in param mode", 4
|
||||
|
||||
|
||||
proc parseUserInput(question: string): int =
|
||||
## Parses a line of user input, showing question to the user first.
|
||||
##
|
||||
## If the user input is an empty line quit() is called. Returns the value
|
||||
## parsed as an integer.
|
||||
while true:
|
||||
echo question
|
||||
let input = stdin.readLine
|
||||
try:
|
||||
result = input.parseInt
|
||||
break
|
||||
except ValueError:
|
||||
if input.len < 1: quit "Blank line detected, quitting.", 0
|
||||
echo "Sorry, `$1' doesn't seem to be a valid integer" % input
|
||||
|
||||
proc interactiveMode() =
|
||||
## Asks the user for two integer values, adds them and exits.
|
||||
let
|
||||
paramA = parseUserInput("Enter the first parameter (blank to exit):")
|
||||
paramB = parseUserInput("Enter the second parameter (blank to exit):")
|
||||
echo "Calculating... $1 + $2 = $3" % [$paramA, $paramB,
|
||||
$backend.myAdd(paramA, paramB)]
|
||||
|
||||
|
||||
when isMainModule:
|
||||
## Main entry point.
|
||||
let opt = parseCmdLine()
|
||||
if cmdParams == opt.action:
|
||||
echo "Param mode: $1 + $2 = $3" % [$opt.paramA, $opt.paramB,
|
||||
$backend.myAdd(opt.paramA, opt.paramB)]
|
||||
else:
|
||||
echo "Entering interactive addition mode"
|
||||
interactiveMode()
|
||||
@@ -1,10 +0,0 @@
|
||||
In this directory you will find the nim commandline version of the
|
||||
cross-calculator sample.
|
||||
|
||||
The commandline interface can be used non interactively through switches, or
|
||||
interactively when running the command without parameters.
|
||||
|
||||
Compilation is fairly easy despite having the source split in different
|
||||
directories. Thanks to the nim.cfg file, which adds the ../nim_backend
|
||||
directory as a search path, you can compile and run the example just fine from
|
||||
the command line with 'nim c -r nimcalculator.nim'.
|
||||
@@ -1,13 +0,0 @@
|
||||
The cross platform calculator illustrates how to use Nim to create a backend
|
||||
called by different native user interfaces.
|
||||
|
||||
Since the purpose of the example is to show how the cross platform code
|
||||
interacts with Nim the actual backend code is just a simple addition proc.
|
||||
By keeping your program logic in Nim you can easily reuse it in different
|
||||
platforms.
|
||||
|
||||
To avoid duplication of code, the backend code lies in a separate directory and
|
||||
each platform compiles it with a different custom build process, usually
|
||||
generating C code in a temporary build directory.
|
||||
|
||||
For a more elaborate and useful example see the cross_todo example.
|
||||
@@ -1,195 +0,0 @@
|
||||
# Backend for a simple todo program with sqlite persistence.
|
||||
#
|
||||
# Most procs dealing with a DbConn object may raise an EDb exception.
|
||||
|
||||
import db_sqlite, parseutils, strutils, times
|
||||
|
||||
type
|
||||
Todo* = object
|
||||
## A todo object holding the information serialized to the database.
|
||||
id: int64 ## Unique identifier of the object in the
|
||||
## database, use the getId() accessor to read it.
|
||||
text*: string ## Description of the task to do.
|
||||
priority*: int ## The priority can be any user defined integer.
|
||||
isDone*: bool ## Done todos are still kept marked.
|
||||
modificationDate: Time ## The modification time can't be modified from
|
||||
## outside of this module, use the
|
||||
## getModificationDate accessor.
|
||||
|
||||
PagedParams* = object
|
||||
## Contains parameters for a query, initialize default values with
|
||||
## initDefaults().
|
||||
pageSize*: int64 ## Lines per returned query page, -1 for
|
||||
## unlimited.
|
||||
priorityAscending*: bool ## Sort results by ascending priority.
|
||||
dateAscending*: bool ## Sort results by ascending modification date.
|
||||
showUnchecked*: bool ## Get unchecked objects.
|
||||
showChecked*: bool ## Get checked objects.
|
||||
|
||||
# - General procs
|
||||
|
||||
proc initDefaults*(params: var PagedParams) =
|
||||
## Sets sane defaults for a PagedParams object.
|
||||
##
|
||||
## Note that you should always provide a non zero pageSize, either a specific
|
||||
## positive value or negative for unbounded query results.
|
||||
params.pageSize = high(int64)
|
||||
params.priorityAscending = false
|
||||
params.dateAscending = false
|
||||
params.showUnchecked = true
|
||||
params.showChecked = false
|
||||
|
||||
proc openDatabase*(path: string): DbConn =
|
||||
## Creates or opens the sqlite3 database.
|
||||
##
|
||||
## Pass the path to the sqlite database, if the database doesn't exist it
|
||||
## will be created. The proc may raise a EDB exception
|
||||
let
|
||||
conn = db_sqlite.open(path, "user", "pass", "db")
|
||||
query = sql"""CREATE TABLE IF NOT EXISTS Todos (
|
||||
id INTEGER PRIMARY KEY,
|
||||
priority INTEGER NOT NULL,
|
||||
is_done BOOLEAN NOT NULL,
|
||||
desc TEXT NOT NULL,
|
||||
modification_date INTEGER NOT NULL,
|
||||
CONSTRAINT Todos UNIQUE (id))"""
|
||||
db_sqlite.exec(conn, query)
|
||||
result = conn
|
||||
|
||||
# - Procs related to Todo objects
|
||||
|
||||
proc initFromDB(id: int64; text: string; priority: int, isDone: bool;
|
||||
modificationDate: Time): Todo =
|
||||
## Returns an initialized Todo object created from database parameters.
|
||||
##
|
||||
## The proc assumes all values are right. Note this proc is NOT exported.
|
||||
assert(id >= 0, "Identity identifiers should not be negative")
|
||||
result.id = id
|
||||
result.text = text
|
||||
result.priority = priority
|
||||
result.isDone = isDone
|
||||
result.modificationDate = modificationDate
|
||||
|
||||
proc getId*(todo: Todo): int64 =
|
||||
## Accessor returning the value of the private id property.
|
||||
return todo.id
|
||||
|
||||
proc getModificationDate*(todo: Todo): Time =
|
||||
## Returns the last modification date of a Todo entry.
|
||||
return todo.modificationDate
|
||||
|
||||
proc update*(todo: var Todo; conn: DbConn): bool =
|
||||
## Checks the database for the object and refreshes its variables.
|
||||
##
|
||||
## Use this method if you (or another entity) have modified the database and
|
||||
## want to update the object you have with whatever the database has stored.
|
||||
## Returns true if the update succeeded, or false if the object was not found
|
||||
## in the database any more, in which case you should probably get rid of the
|
||||
## Todo object.
|
||||
assert(todo.id >= 0, "The identifier of the todo entry can't be negative")
|
||||
let query = sql"""SELECT desc, priority, is_done, modification_date
|
||||
FROM Todos WHERE id = ?"""
|
||||
try:
|
||||
let rows = conn.getAllRows(query, $todo.id)
|
||||
if len(rows) < 1:
|
||||
return
|
||||
assert(1 == len(rows), "Woah, didn't expect so many rows")
|
||||
todo.text = rows[0][0]
|
||||
todo.priority = rows[0][1].parseInt
|
||||
todo.isDone = rows[0][2].parseBool
|
||||
todo.modificationDate = Time(rows[0][3].parseInt)
|
||||
result = true
|
||||
except:
|
||||
echo("Something went wrong selecting for id " & $todo.id)
|
||||
|
||||
proc save*(todo: var Todo; conn: DbConn): bool =
|
||||
## Saves the current state of text, priority and isDone to the database.
|
||||
##
|
||||
## Returns true if the database object was updated (in which case the
|
||||
## modification date will have changed). The proc can return false if the
|
||||
## object wasn't found, for instance, in which case you should drop that
|
||||
## object anyway and create a new one with addTodo(). Also EDb can be raised.
|
||||
assert(todo.id >= 0, "The identifier of the todo entry can't be negative")
|
||||
let
|
||||
currentDate = getTime()
|
||||
query = sql"""UPDATE Todos
|
||||
SET desc = ?, priority = ?, is_done = ?, modification_date = ?
|
||||
WHERE id = ?"""
|
||||
rowsUpdated = conn.execAffectedRows(query, $todo.text,
|
||||
$todo.priority, $todo.isDone, $int(currentDate), $todo.id)
|
||||
if 1 == rowsUpdated:
|
||||
todo.modificationDate = currentDate
|
||||
result = true
|
||||
|
||||
# - Procs dealing directly with the database
|
||||
|
||||
proc addTodo*(conn: DbConn; priority: int; text: string): Todo =
|
||||
## Inserts a new todo into the database.
|
||||
##
|
||||
## Returns the generated todo object. If there is an error EDb will be raised.
|
||||
let
|
||||
currentDate = getTime()
|
||||
query = sql"""INSERT INTO Todos
|
||||
(priority, is_done, desc, modification_date)
|
||||
VALUES (?, 'false', ?, ?)"""
|
||||
todoId = conn.insertId(query, priority, text, $int(currentDate))
|
||||
result = initFromDB(todoId, text, priority, false, currentDate)
|
||||
|
||||
proc deleteTodo*(conn: DbConn; todoId: int64): int64 {.discardable.} =
|
||||
## Deletes the specified todo identifier.
|
||||
##
|
||||
## Returns the number of rows which were affected (1 or 0)
|
||||
let query = sql"""DELETE FROM Todos WHERE id = ?"""
|
||||
result = conn.execAffectedRows(query, $todoId)
|
||||
|
||||
proc getNumEntries*(conn: DbConn): int =
|
||||
## Returns the number of entries in the Todos table.
|
||||
##
|
||||
## If the function succeeds, returns the zero or positive value, if something
|
||||
## goes wrong a negative value is returned.
|
||||
let query = sql"""SELECT COUNT(id) FROM Todos"""
|
||||
try:
|
||||
let row = conn.getRow(query)
|
||||
result = row[0].parseInt
|
||||
except:
|
||||
echo("Something went wrong retrieving number of Todos entries")
|
||||
result = -1
|
||||
|
||||
proc getPagedTodos*(conn: DbConn; params: PagedParams; page = 0'i64): seq[Todo] =
|
||||
## Returns the todo entries for a specific page.
|
||||
##
|
||||
## Pages are calculated based on the params.pageSize parameter, which can be
|
||||
## set to a negative value to specify no limit at all. The query will be
|
||||
## affected by the PagedParams, which should have sane values (call
|
||||
## initDefaults).
|
||||
assert(page >= 0, "You should request a page zero or bigger than zero")
|
||||
result = @[]
|
||||
# Well, if you don't want to see anything, there's no point in asking the db.
|
||||
if not params.showUnchecked and not params.showChecked: return
|
||||
let
|
||||
order_by = [
|
||||
if params.priorityAscending: "ASC" else: "DESC",
|
||||
if params.dateAscending: "ASC" else: "DESC"]
|
||||
query = sql("""SELECT id, desc, priority, is_done, modification_date
|
||||
FROM Todos
|
||||
WHERE is_done = ? OR is_done = ?
|
||||
ORDER BY priority $1, modification_date $2, id DESC
|
||||
LIMIT ? * ?,?""" % order_by)
|
||||
args = @[$params.showChecked, $(not params.showUnchecked),
|
||||
$params.pageSize, $page, $params.pageSize]
|
||||
#echo("Query " & string(query))
|
||||
#echo("args: " & args.join(", "))
|
||||
var newId: BiggestInt
|
||||
for row in conn.fastRows(query, args):
|
||||
let numChars = row[0].parseBiggestInt(newId)
|
||||
assert(numChars > 0, "Huh, couldn't parse identifier from database?")
|
||||
result.add(initFromDB(int64(newId), row[1], row[2].parseInt,
|
||||
row[3].parseBool, Time(row[4].parseInt)))
|
||||
|
||||
proc getTodo*(conn: DbConn; todoId: int64): ref Todo =
|
||||
## Returns a reference to a Todo or nil if the todo could not be found.
|
||||
var tempTodo: Todo
|
||||
tempTodo.id = todoId
|
||||
if tempTodo.update(conn):
|
||||
new(result)
|
||||
result[] = tempTodo
|
||||
@@ -1,14 +0,0 @@
|
||||
This directory contains the nim backend code for the todo cross platform
|
||||
example.
|
||||
|
||||
Unlike the cross platform calculator example, this backend features more code,
|
||||
using an sqlite database for storage. Also a basic test module is provided, not
|
||||
to be included with the final program but to test the exported functionality.
|
||||
The test is not embedded directly in the backend.nim file to avoid being able
|
||||
to access internal data types and procs not exported and replicate the
|
||||
environment of client code.
|
||||
|
||||
In a bigger project with several people you could run `nim doc backend.nim`
|
||||
(or use the doc2 command for a whole project) and provide the generated html
|
||||
documentation to another programer for her to implement an interface without
|
||||
having to look at the source code.
|
||||
@@ -1,74 +0,0 @@
|
||||
# Tests the backend code.
|
||||
|
||||
import backend, db_sqlite, strutils, times
|
||||
|
||||
proc showPagedResults(conn: DbConn; params: PagedParams) =
|
||||
## Shows the contents of the database in pages of specified size.
|
||||
##
|
||||
## Hmm... I guess this is more of a debug proc which should be moved outside,
|
||||
## or to a commandline interface (hint).
|
||||
var
|
||||
page = 0'i64
|
||||
rows = conn.getPagedTodos(params)
|
||||
while rows.len > 0:
|
||||
echo("page " & $page)
|
||||
for row in rows:
|
||||
echo("row id:$1, text:$2, priority:$3, done:$4, date:$5" % [$row.getId,
|
||||
$row.text, $row.priority, $row.isDone,
|
||||
$row.getModificationDate])
|
||||
# Query the database for the next page or quit.
|
||||
if params.pageSize > 0:
|
||||
page = page + 1
|
||||
rows = conn.getPagedTodos(params, page)
|
||||
else:
|
||||
break
|
||||
|
||||
proc dumTest() =
|
||||
let conn = openDatabase("todo.sqlite3")
|
||||
try:
|
||||
let numTodos = conn.getNumEntries
|
||||
echo("Current database contains " & $numTodos & " todo items.")
|
||||
if numTodos < 10:
|
||||
# Fill some dummy rows if there are not many entries yet.
|
||||
discard conn.addTodo(3, "Filler1")
|
||||
discard conn.addTodo(4, "Filler2")
|
||||
var todo = conn.addTodo(2, "Testing")
|
||||
echo("New todo added with id " & $todo.getId)
|
||||
# Try changing it and updating the database.
|
||||
var clonedTodo = conn.getTodo(todo.getId)[]
|
||||
assert(clonedTodo.text == todo.text, "Should be equal")
|
||||
todo.text = "Updated!"
|
||||
todo.priority = 7
|
||||
todo.isDone = true
|
||||
if todo.save(conn):
|
||||
echo("Updated priority $1, done $2" % [$todo.priority, $todo.isDone])
|
||||
else:
|
||||
assert(false, "Uh oh, I wasn't expecting that!")
|
||||
# Verify our cloned copy is different but can be updated.
|
||||
assert(clonedTodo.text != todo.text, "Should be different")
|
||||
discard clonedTodo.update(conn)
|
||||
assert(clonedTodo.text == todo.text, "Should be equal")
|
||||
var params: PagedParams
|
||||
params.initDefaults
|
||||
conn.showPagedResults(params)
|
||||
conn.deleteTodo(todo.getId)
|
||||
echo("Deleted rows for id 3? ")
|
||||
let res = conn.deleteTodo(todo.getId)
|
||||
echo("Deleted rows for id 3? " & $res)
|
||||
if todo.update(conn):
|
||||
echo("Later priority $1, done $2" % [$todo.priority, $todo.isDone])
|
||||
else:
|
||||
echo("Can't update object $1 from db!" % $todo.getId)
|
||||
# Try to list content in a different way.
|
||||
params.pageSize = 5
|
||||
params.priorityAscending = true
|
||||
params.dateAscending = true
|
||||
params.showChecked = true
|
||||
conn.showPagedResults(params)
|
||||
finally:
|
||||
conn.close
|
||||
echo("Database closed")
|
||||
|
||||
# Code that will be run only on the commandline.
|
||||
when isMainModule:
|
||||
dumTest()
|
||||
@@ -1,4 +0,0 @@
|
||||
# Nim configuration file.
|
||||
# The file is used only to add the path of the backend to the compiler options.
|
||||
|
||||
path="../nim_backend"
|
||||
@@ -1,297 +0,0 @@
|
||||
# Implements a command line interface against the backend.
|
||||
|
||||
import backend, db_sqlite, os, parseopt, parseutils, strutils, times
|
||||
|
||||
const
|
||||
USAGE = """nimtodo - Nim cross platform todo manager
|
||||
|
||||
Usage:
|
||||
nimtodo [command] [list options]
|
||||
|
||||
Commands:
|
||||
-a=int text Adds a todo entry with the specified priority and text.
|
||||
-c=int Marks the specified todo entry as done.
|
||||
-u=int Marks the specified todo entry as not done.
|
||||
-d=int|all Deletes a single entry from the database, or all entries.
|
||||
-g Generates some rows with values for testing.
|
||||
-l Lists the contents of the database.
|
||||
-h, --help shows this help
|
||||
|
||||
List options (optional):
|
||||
-p=+|- Sorts list by ascending|descending priority. Default:descending.
|
||||
-m=+|- Sorts list by ascending|descending date. Default:descending.
|
||||
-t Show checked entries. By default they are not shown.
|
||||
-z Hide unchecked entries. By default they are shown.
|
||||
|
||||
Examples:
|
||||
nimtodo -a=4 Water the plants
|
||||
nimtodo -c:87
|
||||
nimtodo -d:2
|
||||
nimtodo -d:all
|
||||
nimtodo -l -p=+ -m=- -t
|
||||
|
||||
"""
|
||||
|
||||
type
|
||||
Command = enum # The possible types of commands
|
||||
cmdAdd # The user wants to add a new todo entry.
|
||||
cmdCheck # User wants to check a todo entry.
|
||||
cmdUncheck # User wants to uncheck a todo entry.
|
||||
cmdDelete # User wants to delete a single todo entry.
|
||||
cmdNuke # User wants to purge all database entries.
|
||||
cmdGenerate # Add random rows to the database, for testing.
|
||||
cmdList # User wants to list contents.
|
||||
|
||||
ParamConfig = object
|
||||
# Structure containing the parsed options from the commandline.
|
||||
command: Command # Store the type of operation
|
||||
addPriority: int # Only valid with cmdAdd, stores priority.
|
||||
addText: seq[string] # Only valid with cmdAdd, stores todo text.
|
||||
todoId: int64 # The todo id for operations like check or delete.
|
||||
listParams: PagedParams # Uses the backend structure directly for params.
|
||||
|
||||
proc initDefaults(params: var ParamConfig) =
|
||||
## Initialises defaults value in the structure.
|
||||
##
|
||||
## Most importantly we want to have an empty list for addText.
|
||||
params.listParams.initDefaults
|
||||
params.addText = @[]
|
||||
|
||||
proc abort(message: string, value: int) =
|
||||
# Simple wrapper to abort also displaying the help to the user.
|
||||
stdout.write(USAGE)
|
||||
quit(message, value)
|
||||
|
||||
template parseTodoIdAndSetCommand(newCommand: Command): untyped =
|
||||
## Helper to parse a big todo identifier into todoId and set command.
|
||||
try:
|
||||
let numChars = val.parseBiggestInt(newId)
|
||||
if numChars < 1: raise newException(ValueError, "Empty string?")
|
||||
result.command = newCommand
|
||||
result.todoId = newId
|
||||
except OverflowError:
|
||||
raise newException(ValueError, "Value $1 too big" % val)
|
||||
|
||||
template verifySingleCommand(actions: typed): typed =
|
||||
## Helper to make sure only one command has been specified so far.
|
||||
if specifiedCommand:
|
||||
abort("Only one command can be specified at a time! (extra:$1)" % [key], 2)
|
||||
else:
|
||||
actions
|
||||
specifiedCommand = true
|
||||
|
||||
proc parsePlusMinus(val: string, debugText: string): bool =
|
||||
## Helper to process a plus or minus character from the commandline.
|
||||
##
|
||||
## Pass the string to parse and the type of parameter for debug errors.
|
||||
## The processed parameter will be returned as true for a '+' and false for a
|
||||
## '-'. The proc aborts with a debug message if the passed parameter doesn't
|
||||
## contain one of those values.
|
||||
case val
|
||||
of "+":
|
||||
return true
|
||||
of "-":
|
||||
return false
|
||||
else:
|
||||
abort("$1 parameter should be + or - but was '$2'." % [debugText, val], 4)
|
||||
|
||||
proc parseCmdLine(): ParamConfig =
|
||||
## Parses the commandline.
|
||||
##
|
||||
## Returns a ParamConfig structure filled with the proper values or directly
|
||||
## calls quit() with the appropriate error message.
|
||||
var
|
||||
specifiedCommand = false
|
||||
usesListParams = false
|
||||
p = initOptParser()
|
||||
key, val: TaintedString
|
||||
newId: BiggestInt
|
||||
result.initDefaults
|
||||
try:
|
||||
while true:
|
||||
next(p)
|
||||
key = p.key
|
||||
val = p.val
|
||||
case p.kind
|
||||
of cmdArgument:
|
||||
if specifiedCommand and cmdAdd == result.command:
|
||||
result.addText.add(key)
|
||||
else:
|
||||
abort("Argument ($1) detected without add command." % [key], 1)
|
||||
of cmdLongOption, cmdShortOption:
|
||||
case normalize(key)
|
||||
of "help", "h":
|
||||
stdout.write(USAGE)
|
||||
quit(0)
|
||||
of "a":
|
||||
verifySingleCommand:
|
||||
result.command = cmdAdd
|
||||
result.addPriority = val.parseInt
|
||||
of "c":
|
||||
verifySingleCommand:
|
||||
parseTodoIdAndSetCommand(cmdCheck)
|
||||
of "u":
|
||||
verifySingleCommand:
|
||||
parseTodoIdAndSetCommand cmdUncheck
|
||||
of "d":
|
||||
verifySingleCommand:
|
||||
if "all" == val:
|
||||
result.command = cmdNuke
|
||||
else:
|
||||
parseTodoIdAndSetCommand cmdDelete
|
||||
of "g":
|
||||
verifySingleCommand:
|
||||
if val.len > 0:
|
||||
abort("Unexpected value '$1' for switch l." % [val], 3)
|
||||
result.command = cmdGenerate
|
||||
of "l":
|
||||
verifySingleCommand:
|
||||
if val.len > 0:
|
||||
abort("Unexpected value '$1' for switch l." % [val], 3)
|
||||
result.command = cmdList
|
||||
of "p":
|
||||
usesListParams = true
|
||||
result.listParams.priorityAscending = parsePlusMinus(val, "Priority")
|
||||
of "m":
|
||||
usesListParams = true
|
||||
result.listParams.dateAscending = parsePlusMinus(val, "Date")
|
||||
of "t":
|
||||
usesListParams = true
|
||||
if val.len > 0:
|
||||
abort("Unexpected value '$1' for switch t." % [val], 5)
|
||||
result.listParams.showChecked = true
|
||||
of "z":
|
||||
usesListParams = true
|
||||
if val.len > 0:
|
||||
abort("Unexpected value '$1' for switch z." % [val], 5)
|
||||
result.listParams.showUnchecked = false
|
||||
else:
|
||||
abort("Unexpected option '$1'." % [key], 6)
|
||||
of cmdEnd:
|
||||
break
|
||||
except ValueError:
|
||||
abort("Invalid integer value '$1' for parameter '$2'." % [val, key], 7)
|
||||
if not specifiedCommand:
|
||||
abort("Didn't specify any command.", 8)
|
||||
if cmdAdd == result.command and result.addText.len < 1:
|
||||
abort("Used the add command, but provided no text/description.", 9)
|
||||
if usesListParams and cmdList != result.command:
|
||||
abort("Used list options, but didn't specify the list command.", 10)
|
||||
|
||||
proc generateDatabaseRows(conn: DbConn) =
|
||||
## Adds some rows to the database ignoring errors.
|
||||
discard conn.addTodo(1, "Watch another random youtube video")
|
||||
discard conn.addTodo(2, "Train some starcraft moves for the league")
|
||||
discard conn.addTodo(3, "Spread the word about Nim")
|
||||
discard conn.addTodo(4, "Give fruit superavit to neighbours")
|
||||
var todo = conn.addTodo(4, "Send tax form through snail mail")
|
||||
todo.isDone = true
|
||||
discard todo.save(conn)
|
||||
discard conn.addTodo(1, "Download new anime to watch")
|
||||
todo = conn.addTodo(2, "Build train model from scraps")
|
||||
todo.isDone = true
|
||||
discard todo.save(conn)
|
||||
discard conn.addTodo(5, "Buy latest Britney Spears album")
|
||||
discard conn.addTodo(6, "Learn a functional programming language")
|
||||
echo("Generated some entries, they were added to your database.")
|
||||
|
||||
proc listDatabaseContents(conn: DbConn; listParams: PagedParams) =
|
||||
## Dumps the database contents formatted to the standard output.
|
||||
##
|
||||
## Pass the list/filter parameters parsed from the commandline.
|
||||
var params = listParams
|
||||
params.pageSize = -1
|
||||
let todos = conn.getPagedTodos(params)
|
||||
if todos.len < 1:
|
||||
echo("Database empty")
|
||||
return
|
||||
echo("Todo id, is done, priority, last modification date, text:")
|
||||
# First detect how long should be our columns for formatting.
|
||||
var cols: array[0..2, int]
|
||||
for todo in todos:
|
||||
cols[0] = max(cols[0], ($todo.getId).len)
|
||||
cols[1] = max(cols[1], ($todo.priority).len)
|
||||
cols[2] = max(cols[2], ($todo.getModificationDate).len)
|
||||
# Now dump all the rows using the calculated alignment sizes.
|
||||
for todo in todos:
|
||||
echo("$1 $2 $3, $4, $5" % [
|
||||
($todo.getId).align(cols[0]),
|
||||
if todo.isDone: "[X]" else: "[-]",
|
||||
($todo.priority).align(cols[1]),
|
||||
($todo.getModificationDate).align(cols[2]),
|
||||
todo.text])
|
||||
|
||||
proc deleteOneTodo(conn: DbConn; todoId: int64) =
|
||||
## Deletes a single todo entry from the database.
|
||||
let numDeleted = conn.deleteTodo(todoId)
|
||||
if numDeleted > 0:
|
||||
echo("Deleted todo id " & $todoId)
|
||||
else:
|
||||
quit("Couldn't delete todo id " & $todoId, 11)
|
||||
|
||||
proc deleteAllTodos(conn: DbConn) =
|
||||
## Deletes all the contents from the database.
|
||||
##
|
||||
## Note that it would be more optimal to issue a direct DELETE sql statement
|
||||
## on the database, but for the sake of the example we will restrict
|
||||
## ourselfves to the API exported by backend.
|
||||
var
|
||||
counter: int64
|
||||
params: PagedParams
|
||||
params.initDefaults
|
||||
params.pageSize = -1
|
||||
params.showUnchecked = true
|
||||
params.showChecked = true
|
||||
let todos = conn.getPagedTodos(params)
|
||||
for todo in todos:
|
||||
if conn.deleteTodo(todo.getId) > 0:
|
||||
counter += 1
|
||||
else:
|
||||
quit("Couldn't delete todo id " & $todo.getId, 12)
|
||||
echo("Deleted $1 todo entries from database." % $counter)
|
||||
|
||||
proc setTodoCheck(conn: DbConn; todoId: int64; value: bool) =
|
||||
## Changes the check state of a todo entry to the specified value.
|
||||
let
|
||||
newState = if value: "checked" else: "unchecked"
|
||||
todo = conn.getTodo(todoId)
|
||||
if todo == nil:
|
||||
quit("Can't modify todo id $1, its not in the database." % $todoId, 13)
|
||||
if todo[].isDone == value:
|
||||
echo("Todo id $1 was already set to $2." % [$todoId, newState])
|
||||
return
|
||||
todo[].isDone = value
|
||||
if todo[].save(conn):
|
||||
echo("Todo id $1 set to $2." % [$todoId, newState])
|
||||
else:
|
||||
quit("Error updating todo id $1 to $2." % [$todoId, newState])
|
||||
|
||||
proc addTodo(conn: DbConn; priority: int; tokens: seq[string]) =
|
||||
## Adds to the database a todo with the specified priority.
|
||||
##
|
||||
## The tokens are joined as a single string using the space character. The
|
||||
## created id will be displayed to the user.
|
||||
let todo = conn.addTodo(priority, tokens.join(" "))
|
||||
echo("Created todo entry with id:$1 for priority $2 and text '$3'." % [
|
||||
$todo.getId, $todo.priority, todo.text])
|
||||
|
||||
when isMainModule:
|
||||
## Main entry point.
|
||||
let
|
||||
opt = parseCmdLine()
|
||||
dbPath = getConfigDir() / "nimtodo.sqlite3"
|
||||
if not dbPath.existsFile:
|
||||
createDir(getConfigDir())
|
||||
echo("No database found at $1, it will be created for you." % dbPath)
|
||||
let conn = openDatabase(dbPath)
|
||||
try:
|
||||
case opt.command
|
||||
of cmdAdd: addTodo(conn, opt.addPriority, opt.addText)
|
||||
of cmdCheck: setTodoCheck(conn, opt.todoId, true)
|
||||
of cmdUncheck: setTodoCheck(conn, opt.todoId, false)
|
||||
of cmdDelete: deleteOneTodo(conn, opt.todoId)
|
||||
of cmdNuke: deleteAllTodos(conn)
|
||||
of cmdGenerate: generateDatabaseRows(conn)
|
||||
of cmdList: listDatabaseContents(conn, opt.listParams)
|
||||
finally:
|
||||
conn.close
|
||||
@@ -1,19 +0,0 @@
|
||||
This directory contains the Nim commandline version of the todo cross
|
||||
platform example.
|
||||
|
||||
The commandline interface can be used only through switches, running the binary
|
||||
once will spit out the basic help. The commands you can use are the typical on
|
||||
such an application: add, check/uncheck and delete (further could be added,
|
||||
like modification at expense of parsing/option complexity). The list command is
|
||||
the only one which dumps the contents of the database. The output can be
|
||||
filtered and sorted through additional parameters.
|
||||
|
||||
When you run the program for the first time the todo database will be generated
|
||||
in your user's data directory. To cope with an empty database, a special
|
||||
generation switch can be used to fill the database with some basic todo entries
|
||||
you can play with.
|
||||
|
||||
Compilation is fairly easy despite having the source split in different
|
||||
directories. Thanks to the nim.cfg file, which adds the ../Nim_backend
|
||||
directory as a search path, you can compile and run the example just fine from
|
||||
the command line with 'nim c -r nimtodo.nim'.
|
||||
@@ -1,5 +0,0 @@
|
||||
This cross platform todo illustrates how to use Nim to create a backend
|
||||
called by different native user interfaces.
|
||||
|
||||
This example builds on the knowledge learned from the cross_calculator example.
|
||||
Check it out first to learn how to set up Nim on different platforms.
|
||||
@@ -1,17 +0,0 @@
|
||||
# Simple program to test the debugger
|
||||
# compile with --debugger:on
|
||||
|
||||
proc someComp(x, y: int): int =
|
||||
let a = x+y
|
||||
if a > 7:
|
||||
let b = a*90
|
||||
{.breakpoint.}
|
||||
result = b
|
||||
{.breakpoint.}
|
||||
|
||||
proc pp() =
|
||||
var aa = 45
|
||||
var bb = "abcdef"
|
||||
echo someComp(23, 45)
|
||||
|
||||
pp()
|
||||
@@ -1,23 +0,0 @@
|
||||
#? stdtmpl | standard
|
||||
#proc generateHTMLPage(title, currentTab, content: string,
|
||||
# tabs: openArray[string]): string =
|
||||
# result = ""
|
||||
<head><title>$title</title></head>
|
||||
<body>
|
||||
<div id="menu">
|
||||
<ul>
|
||||
#for tab in items(tabs):
|
||||
#if currentTab == tab:
|
||||
<li><a id="selected"
|
||||
#else:
|
||||
<li><a
|
||||
#end if
|
||||
href="${tab}.html" title = "$title - $tab">$tab</a></li>
|
||||
#end for
|
||||
</ul>
|
||||
</div>
|
||||
<div id="content">
|
||||
$content
|
||||
A dollar: $$.
|
||||
</div>
|
||||
</body>
|
||||
@@ -1,14 +0,0 @@
|
||||
# Fizz Buzz program
|
||||
|
||||
const f = "Fizz"
|
||||
const b = "Buzz"
|
||||
for i in 1..100:
|
||||
if i mod 15 == 0:
|
||||
echo f, b
|
||||
elif i mod 5 == 0:
|
||||
echo b
|
||||
elif i mod 3 == 0:
|
||||
echo f
|
||||
else:
|
||||
echo i
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# Example program to show the new parsexml module
|
||||
# This program reads an HTML file and writes all its used links to stdout.
|
||||
# Errors and whitespace are ignored.
|
||||
|
||||
import os, streams, parsexml, strutils
|
||||
|
||||
proc `=?=` (a, b: string): bool =
|
||||
# little trick: define our own comparator that ignores case
|
||||
return cmpIgnoreCase(a, b) == 0
|
||||
|
||||
if paramCount() < 1:
|
||||
quit("Usage: htmlrefs filename[.html]")
|
||||
|
||||
var links = 0 # count the number of links
|
||||
var filename = addFileExt(paramStr(1), "html")
|
||||
var s = newFileStream(filename, fmRead)
|
||||
if s == nil: quit("cannot open the file " & filename)
|
||||
var x: XmlParser
|
||||
open(x, s, filename)
|
||||
next(x) # get first event
|
||||
block mainLoop:
|
||||
while true:
|
||||
case x.kind
|
||||
of xmlElementOpen:
|
||||
# the <a href = "xyz"> tag we are interested in always has an attribute,
|
||||
# thus we search for ``xmlElementOpen`` and not for ``xmlElementStart``
|
||||
if x.elementName =?= "a":
|
||||
x.next()
|
||||
if x.kind == xmlAttribute:
|
||||
if x.attrKey =?= "href":
|
||||
var link = x.attrValue
|
||||
inc(links)
|
||||
# skip until we have an ``xmlElementClose`` event
|
||||
while true:
|
||||
x.next()
|
||||
case x.kind
|
||||
of xmlEof: break mainLoop
|
||||
of xmlElementClose: break
|
||||
else: discard
|
||||
x.next() # skip ``xmlElementClose``
|
||||
# now we have the description for the ``a`` element
|
||||
var desc = ""
|
||||
while x.kind == xmlCharData:
|
||||
desc.add(x.charData)
|
||||
x.next()
|
||||
echo(desc & ": " & link)
|
||||
else:
|
||||
x.next()
|
||||
of xmlEof: break # end of file reached
|
||||
of xmlError:
|
||||
echo(errorMsg(x))
|
||||
x.next()
|
||||
else: x.next() # skip other events
|
||||
|
||||
echo($links & " link(s) found!")
|
||||
x.close()
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Example program to show the parsexml module
|
||||
# This program reads an HTML file and writes its title to stdout.
|
||||
# Errors and whitespace are ignored.
|
||||
|
||||
import os, streams, parsexml, strutils
|
||||
|
||||
if paramCount() < 1:
|
||||
quit("Usage: htmltitle filename[.html]")
|
||||
|
||||
var filename = addFileExt(paramStr(1), "html")
|
||||
var s = newFileStream(filename, fmRead)
|
||||
if s == nil: quit("cannot open the file " & filename)
|
||||
var x: XmlParser
|
||||
open(x, s, filename)
|
||||
while true:
|
||||
x.next()
|
||||
case x.kind
|
||||
of xmlElementStart:
|
||||
if cmpIgnoreCase(x.elementName, "title") == 0:
|
||||
var title = ""
|
||||
x.next() # skip "<title>"
|
||||
while x.kind == xmlCharData:
|
||||
title.add(x.charData)
|
||||
x.next()
|
||||
if x.kind == xmlElementEnd and cmpIgnoreCase(x.elementName, "title") == 0:
|
||||
echo("Title: " & title)
|
||||
quit(0) # Success!
|
||||
else:
|
||||
echo(x.errorMsgExpected("/title"))
|
||||
|
||||
of xmlEof: break # end of file reached
|
||||
else: discard # ignore other events
|
||||
|
||||
x.close()
|
||||
quit("Could not determine title!")
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
import strutils, os, osproc, strtabs, streams, sockets
|
||||
|
||||
const
|
||||
wwwNL* = "\r\L"
|
||||
ServerSig = "Server: httpserver.nim/1.0.0" & wwwNL
|
||||
|
||||
type
|
||||
TRequestMethod = enum reqGet, reqPost
|
||||
TServer* = object ## contains the current server state
|
||||
s: Socket
|
||||
job: seq[TJob]
|
||||
TJob* = object
|
||||
client: Socket
|
||||
process: Process
|
||||
|
||||
# --------------- output messages --------------------------------------------
|
||||
|
||||
proc sendTextContentType(client: Socket) =
|
||||
send(client, "Content-type: text/html" & wwwNL)
|
||||
send(client, wwwNL)
|
||||
|
||||
proc badRequest(client: Socket) =
|
||||
# Inform the client that a request it has made has a problem.
|
||||
send(client, "HTTP/1.0 400 BAD REQUEST" & wwwNL)
|
||||
sendTextContentType(client)
|
||||
send(client, "<p>Your browser sent a bad request, " &
|
||||
"such as a POST without a Content-Length.</p>" & wwwNL)
|
||||
|
||||
|
||||
proc cannotExec(client: Socket) =
|
||||
send(client, "HTTP/1.0 500 Internal Server Error" & wwwNL)
|
||||
sendTextContentType(client)
|
||||
send(client, "<P>Error prohibited CGI execution.</p>" & wwwNL)
|
||||
|
||||
|
||||
proc headers(client: Socket, filename: string) =
|
||||
# XXX could use filename to determine file type
|
||||
send(client, "HTTP/1.0 200 OK" & wwwNL)
|
||||
send(client, ServerSig)
|
||||
sendTextContentType(client)
|
||||
|
||||
proc notFound(client: Socket, path: string) =
|
||||
send(client, "HTTP/1.0 404 NOT FOUND" & wwwNL)
|
||||
send(client, ServerSig)
|
||||
sendTextContentType(client)
|
||||
send(client, "<html><title>Not Found</title>" & wwwNL)
|
||||
send(client, "<body><p>The server could not fulfill" & wwwNL)
|
||||
send(client, "your request because the resource <b>" & path & "</b>" & wwwNL)
|
||||
send(client, "is unavailable or nonexistent.</p>" & wwwNL)
|
||||
send(client, "</body></html>" & wwwNL)
|
||||
|
||||
|
||||
proc unimplemented(client: Socket) =
|
||||
send(client, "HTTP/1.0 501 Method Not Implemented" & wwwNL)
|
||||
send(client, ServerSig)
|
||||
sendTextContentType(client)
|
||||
send(client, "<html><head><title>Method Not Implemented" &
|
||||
"</title></head>" &
|
||||
"<body><p>HTTP request method not supported.</p>" &
|
||||
"</body></HTML>" & wwwNL)
|
||||
|
||||
|
||||
# ----------------- file serving ---------------------------------------------
|
||||
|
||||
proc discardHeaders(client: Socket) = skip(client)
|
||||
|
||||
proc serveFile(client: Socket, filename: string) =
|
||||
discardHeaders(client)
|
||||
|
||||
var f: File
|
||||
if open(f, filename):
|
||||
headers(client, filename)
|
||||
const bufSize = 8000 # != 8K might be good for memory manager
|
||||
var buf = alloc(bufsize)
|
||||
while true:
|
||||
var bytesread = readBuffer(f, buf, bufsize)
|
||||
if bytesread > 0:
|
||||
var byteswritten = send(client, buf, bytesread)
|
||||
if bytesread != bytesWritten:
|
||||
let err = osLastError()
|
||||
dealloc(buf)
|
||||
close(f)
|
||||
raiseOSError(err)
|
||||
if bytesread != bufSize: break
|
||||
dealloc(buf)
|
||||
close(f)
|
||||
client.close()
|
||||
else:
|
||||
notFound(client, filename)
|
||||
|
||||
# ------------------ CGI execution -------------------------------------------
|
||||
|
||||
proc executeCgi(server: var TServer, client: Socket, path, query: string,
|
||||
meth: TRequestMethod) =
|
||||
var env = newStringTable(modeCaseInsensitive)
|
||||
var contentLength = -1
|
||||
case meth
|
||||
of reqGet:
|
||||
discardHeaders(client)
|
||||
|
||||
env["REQUEST_METHOD"] = "GET"
|
||||
env["QUERY_STRING"] = query
|
||||
of reqPost:
|
||||
var buf = ""
|
||||
var dataAvail = true
|
||||
while dataAvail:
|
||||
dataAvail = recvLine(client, buf)
|
||||
if buf.len == 0:
|
||||
break
|
||||
var L = toLowerAscii(buf)
|
||||
if L.startsWith("content-length:"):
|
||||
var i = len("content-length:")
|
||||
while L[i] in Whitespace: inc(i)
|
||||
contentLength = parseInt(substr(L, i))
|
||||
|
||||
if contentLength < 0:
|
||||
badRequest(client)
|
||||
return
|
||||
|
||||
env["REQUEST_METHOD"] = "POST"
|
||||
env["CONTENT_LENGTH"] = $contentLength
|
||||
|
||||
send(client, "HTTP/1.0 200 OK" & wwwNL)
|
||||
|
||||
var process = startProcess(command=path, env=env)
|
||||
|
||||
var job: TJob
|
||||
job.process = process
|
||||
job.client = client
|
||||
server.job.add(job)
|
||||
|
||||
if meth == reqPost:
|
||||
# get from client and post to CGI program:
|
||||
var buf = alloc(contentLength)
|
||||
if recv(client, buf, contentLength) != contentLength:
|
||||
let err = osLastError()
|
||||
dealloc(buf)
|
||||
raiseOSError(err)
|
||||
var inp = process.inputStream
|
||||
inp.writeData(buf, contentLength)
|
||||
dealloc(buf)
|
||||
|
||||
proc animate(server: var TServer) =
|
||||
# checks list of jobs, removes finished ones (pretty sloppy by seq copying)
|
||||
var active_jobs: seq[TJob] = @[]
|
||||
for i in 0..server.job.len-1:
|
||||
var job = server.job[i]
|
||||
if running(job.process):
|
||||
active_jobs.add(job)
|
||||
else:
|
||||
# read process output stream and send it to client
|
||||
var outp = job.process.outputStream
|
||||
while true:
|
||||
var line = outp.readstr(1024)
|
||||
if line.len == 0:
|
||||
break
|
||||
else:
|
||||
try:
|
||||
send(job.client, line)
|
||||
except:
|
||||
echo("send failed, client diconnected")
|
||||
close(job.client)
|
||||
|
||||
server.job = active_jobs
|
||||
|
||||
# --------------- Server Setup -----------------------------------------------
|
||||
|
||||
proc acceptRequest(server: var TServer, client: Socket) =
|
||||
var cgi = false
|
||||
var query = ""
|
||||
var buf = ""
|
||||
discard recvLine(client, buf)
|
||||
var path = ""
|
||||
var data = buf.split()
|
||||
var meth = reqGet
|
||||
var q = find(data[1], '?')
|
||||
|
||||
# extract path
|
||||
if q >= 0:
|
||||
# strip "?..." from path, this may be found in both POST and GET
|
||||
path = data[1].substr(0, q-1)
|
||||
else:
|
||||
path = data[1]
|
||||
# path starts with "/", by adding "." in front of it we serve files from cwd
|
||||
path = "." & path
|
||||
|
||||
echo("accept: " & path)
|
||||
|
||||
if cmpIgnoreCase(data[0], "GET") == 0:
|
||||
if q >= 0:
|
||||
cgi = true
|
||||
query = data[1].substr(q+1)
|
||||
elif cmpIgnoreCase(data[0], "POST") == 0:
|
||||
cgi = true
|
||||
meth = reqPost
|
||||
else:
|
||||
unimplemented(client)
|
||||
|
||||
if path[path.len-1] == '/' or existsDir(path):
|
||||
path = path / "index.html"
|
||||
|
||||
if not existsFile(path):
|
||||
discardHeaders(client)
|
||||
notFound(client, path)
|
||||
client.close()
|
||||
else:
|
||||
when defined(Windows):
|
||||
var ext = splitFile(path).ext.toLowerAscii
|
||||
if ext == ".exe" or ext == ".cgi":
|
||||
# XXX: extract interpreter information here?
|
||||
cgi = true
|
||||
else:
|
||||
if {fpUserExec, fpGroupExec, fpOthersExec} * path.getFilePermissions != {}:
|
||||
cgi = true
|
||||
if not cgi:
|
||||
serveFile(client, path)
|
||||
else:
|
||||
executeCgi(server, client, path, query, meth)
|
||||
|
||||
when isMainModule:
|
||||
var port = 80
|
||||
|
||||
var server: TServer
|
||||
server.job = @[]
|
||||
server.s = socket(AF_INET)
|
||||
if server.s == invalidSocket: raiseOSError(osLastError())
|
||||
server.s.bindAddr(port=Port(port))
|
||||
listen(server.s)
|
||||
echo("server up on port " & $port)
|
||||
|
||||
while true:
|
||||
# check for new new connection & handle it
|
||||
var list: seq[Socket] = @[server.s]
|
||||
if select(list, 10) > 0:
|
||||
var client: Socket
|
||||
new(client)
|
||||
accept(server.s, client)
|
||||
try:
|
||||
acceptRequest(server, client)
|
||||
except:
|
||||
echo("failed to accept client request")
|
||||
|
||||
# pooling events
|
||||
animate(server)
|
||||
# some slack for CPU
|
||||
sleep(10)
|
||||
server.s.close()
|
||||
@@ -1,4 +1,4 @@
|
||||
# Test high level features
|
||||
# Shows how the method call syntax can be used to chain calls conveniently.
|
||||
|
||||
import strutils, sequtils
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# horrible example of how to interface with GNUStep ...
|
||||
|
||||
{.passL: "-lobjc".}
|
||||
{.emit: """
|
||||
|
||||
#include <objc/Object.h>
|
||||
|
||||
@interface Greeter:Object
|
||||
{
|
||||
}
|
||||
|
||||
- (void)greet:(long)x y:(long)dummy;
|
||||
|
||||
@end
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@implementation Greeter
|
||||
|
||||
- (void)greet:(long)x y:(long)dummy
|
||||
{
|
||||
printf("Hello, World!\n");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#include <stdlib.h>
|
||||
""".}
|
||||
|
||||
type
|
||||
TId {.importc: "id", header: "<objc/Object.h>", final.} = distinct int
|
||||
|
||||
proc newGreeter: TId {.importobjc: "Greeter new", nodecl.}
|
||||
proc greet(self: TId, x, y: int) {.importobjc: "greet", nodecl.}
|
||||
proc free(self: TId) {.importobjc: "free", nodecl.}
|
||||
|
||||
var g = newGreeter()
|
||||
g.greet(12, 34)
|
||||
g.free()
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
import
|
||||
os, parsecfg, strutils, streams
|
||||
|
||||
var f = newFileStream(paramStr(1), fmRead)
|
||||
if f != nil:
|
||||
var p: CfgParser
|
||||
open(p, f, paramStr(1))
|
||||
while true:
|
||||
var e = next(p)
|
||||
case e.kind
|
||||
of cfgEof:
|
||||
echo("EOF!")
|
||||
break
|
||||
of cfgSectionStart: ## a ``[section]`` has been parsed
|
||||
echo("new section: " & e.section)
|
||||
of cfgKeyValuePair:
|
||||
echo("key-value-pair: " & e.key & ": " & e.value)
|
||||
of cfgOption:
|
||||
echo("command: " & e.key & ": " & e.value)
|
||||
of cfgError:
|
||||
echo(e.msg)
|
||||
close(p)
|
||||
else:
|
||||
echo("cannot open: " & paramStr(1))
|
||||
@@ -1,2 +1,2 @@
|
||||
In this directory you will find several examples for how to use the Nim
|
||||
In this directory you can find several examples for how to use the Nim
|
||||
library.
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# Stores extra data inside the SSL context.
|
||||
import net
|
||||
|
||||
let ctx = newContext()
|
||||
|
||||
# Our unique index for storing foos
|
||||
let fooIndex = ctx.getExtraDataIndex()
|
||||
# And another unique index for storing foos
|
||||
let barIndex = ctx.getExtraDataIndex()
|
||||
echo "got indexes ", fooIndex, " ", barIndex
|
||||
|
||||
try:
|
||||
discard ctx.getExtraData(fooIndex)
|
||||
assert false
|
||||
except IndexError:
|
||||
echo("Success")
|
||||
|
||||
type
|
||||
FooRef = ref object of RootRef
|
||||
foo: int
|
||||
|
||||
let foo = FooRef(foo: 5)
|
||||
ctx.setExtraData(fooIndex, foo)
|
||||
doAssert ctx.getExtraData(fooIndex).FooRef == foo
|
||||
|
||||
ctx.destroyContext()
|
||||
@@ -1,16 +0,0 @@
|
||||
# Create connection encrypted using preshared key (TLS-PSK).
|
||||
import net
|
||||
|
||||
static: assert defined(ssl)
|
||||
|
||||
let sock = newSocket()
|
||||
sock.connect("localhost", Port(8800))
|
||||
|
||||
proc clientFunc(identityHint: string): tuple[identity: string, psk: string] =
|
||||
echo "identity hint ", identityHint.repr
|
||||
return ("foo", "psk-of-foo")
|
||||
|
||||
let context = newContext(cipherList="PSK-AES256-CBC-SHA")
|
||||
context.clientGetPskFunc = clientFunc
|
||||
context.wrapConnectedSocket(sock, handshakeAsClient)
|
||||
context.destroyContext()
|
||||
@@ -1,20 +0,0 @@
|
||||
# Accept connection encrypted using preshared key (TLS-PSK).
|
||||
import net
|
||||
|
||||
static: assert defined(ssl)
|
||||
|
||||
let sock = newSocket()
|
||||
sock.bindAddr(Port(8800))
|
||||
sock.listen()
|
||||
|
||||
let context = newContext(cipherList="PSK-AES256-CBC-SHA")
|
||||
context.pskIdentityHint = "hello"
|
||||
context.serverGetPskFunc = proc(identity: string): string = "psk-of-" & identity
|
||||
|
||||
while true:
|
||||
var client = new(Socket)
|
||||
sock.accept(client)
|
||||
sock.setSockOpt(OptReuseAddr, true)
|
||||
echo "accepted connection"
|
||||
context.wrapConnectedSocket(client, handshakeAsServer)
|
||||
echo "got connection with identity ", client.getPskIdentity()
|
||||
@@ -1,8 +0,0 @@
|
||||
# Shows how to transform a file
|
||||
|
||||
import pegs
|
||||
|
||||
transformFile("infile.txt", "outfile.txt",
|
||||
[(peg"""S <- {typedesc} \s* {\ident} \s* ','
|
||||
typedesc <- \ident '*'* """, r"$2: $1")])
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import net
|
||||
|
||||
let sock = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)
|
||||
|
||||
sock.connectUnix("sock")
|
||||
sock.send("hello\n")
|
||||
@@ -1,14 +0,0 @@
|
||||
import net
|
||||
|
||||
let sock = newSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)
|
||||
sock.bindUnix("sock")
|
||||
sock.listen()
|
||||
|
||||
while true:
|
||||
var client = new(Socket)
|
||||
sock.accept(client)
|
||||
var output = ""
|
||||
output.setLen 32
|
||||
client.readLine(output)
|
||||
echo "got ", output
|
||||
client.close()
|
||||
Reference in New Issue
Block a user