Showing posts with label tricks. Show all posts
Showing posts with label tricks. Show all posts

Tuesday, April 19, 2016

Call me! PythonJS and variadic functions

I’m currently developing UI automation tests for Adobe Experience Design, aka Adobe XD. Or, for anybody who hasn’t heard of the recent name change: Project Comet!

Combine and attach different material 

1. This is a note to myself. Mostly

Today, I got stuck in something that looked pretty straight forward to me. I wanted to call a function in a Python API from my JavaScript code. We use PythonJS to make this magic happen. In the most cases, calling a function in the Python API is not a big deal. Scalar values work well, named arguments work well, but variadic function args do not.
The function I wanted to call looks like this:

def menuItem(self, *args)
Calling the function from JavaScript, I tried several things. The most promising for me was to convert the JavaScript arguments into an Array and pass it on.

pythonObj.menuItem(['value1', 'value2', 'value3'])
The result was an error, telling me that I should call the function with a string or int. Okay, the function signature accept either one or multiple `int`s or `string`s. In various combinations.
I guess, my initial approach was a bit too naive. A JavaScript array doesn’t translate to a vararg in Python. Got it! But how do I pass the list of varargs from JavaScript to Python? I tried to apply the arguments from the JavaScript function to obj.menuItem. But this didn’t work with the same error.
I tried to call the Python function by

obj.menuItem("value1", "value2", "value3")
That worked well. But I can’t make this happen from the JavaScript side? How can I split up an unknown number of arguments and pass them all as single arguments? I had no answer for that.

2. Workaround, Hack, you name it

If I would have a fixed number of arguments, the solution would be easier. I ended up with a hacky solution (IMHO), since I didn’t wanted to spent more time on this interesting but blocking issue.

function callPythonFunction(args) {
    switch (args.length) {
        case 1: {
            return app.menuItem(args[0]);
        }

        case 2: {
            return app.menuItem(args[0], args[1]);
        }

        case 3: {
            return app.menuItem(args[0], args[1], args[2]);
        }

        default:
            console.error("Unsupported amount of arguments for args", args.length);
        }
}
Is this a good solution? Until I find something better, I consider it as a good solution.

3. Summary

Bridging languages and make up for missing or non transferrable features requires creative solutions. They might not be the best solutions, but they unblock and let you move on.

What do you think? Is there a better way of doing this? Let me know in the comments.

Thanks for reading!

Saturday, March 5, 2016

5 npm script secrets

No Secret

Last week I was hosting a workshop about Electron Shell, ES6 and Reactjs at ForwardJS in San Francisco. Preparing all the sample code, I was inspired by this blog post to avoid any build tool like grunt or gulp at all. In fact, I wanted to remove anything that could distract the attendees of the workshop by throwing another unknown toolset at them. Instead, leveraging the build in capabilities of npm.

The Idea

Why use grunt, gulp, etc. if you can leverage the power of npm scripts? Not having to maintain a build script is a good idea and helps to remove another piece of complexity from your project.

Secrets

Different types of scripts

npm supports custom scripts defined by scripts property of package.json. npm distinguishes between 2 different kind of scripts

  • lifecycle scripts

  • directly-run scripts

Lifecycle scripts tie into a specific phase of your project lifecycle, like install, publish, start, stop, etc. These scripts can be executed with npm lifecycle-script. Each lifecycle script can have a pre and post script for that phase, e.g. preinstall and postinstall.

The directly-run scripts need the extra run command after npm, e.g. npm run *my-script-name*. Your directly-run scripts can have a pre and post step with the same name as your script name, e.g. premy-script-name and *postmy-script-name. Always without space between the prefix and the script name.

You can read more about it in the official docs.

Tip Call your own scripts always with npm run <script-name>.

Platform differences

Sometimes you need to do things differenly when it comes to build your project on multiple platforms. I ran into the issue, where I needed to copy files. On OSX this is as simple as cp srcfile.txt destfile.txt. On Windows, this didn’t work, since cp is an unknown command, unless you have cygwin installed. Building your project in the default Windows command prompt fails with an error, once you want to copy those important files. On Windows you should use copy instead.

Tip Create an external copy.js file and do the OS specific tasks there. You can use process.platform === 'win32' to determine if you are running Windows.

DRY - refer to anything defined in your package.json

DRY (don’t repeat yourself) is a great principle when it comes to software development. You can even refer to anything defined in your package.json when you execute your script. Let’s assume, you want to create a zip for distribution.

"scripts": {
    "create-zip": "zip -r app-1.0.zip dist"
}

Now you can call npm run create-zip to create a zip containing all the files to distribute your app.

But why can’t we just refer to the name of the app and the version already defined in package.json? Well, we can. npm exposes all config keys from package.json in the form npm_package_configkey for you to use in your scripts.

"scripts": {
    "create-zip": "zip -r $npm_package_name-$npm_package_version.zip $npm_package_distdir"
}
Tip Stay DRY! Refer to information already available in package.json. You can define whatever config option in package.json and refer to it in the same way.

Call any script in another script

What if you want to run more than one script at the same time? You want for example watch *.js files and *.scss files and preprocess them? How can you do this with one npm script?

You can concatenate different scripts and run them all at the same time:

"scripts": {
    "sass-watch": "node-sass -watch src/style.scss dest/style.css",
    "babel-watch": "babel -w *.js dist",
    "watch": "npm run sass-watch & npm run babel-watch" // 1
}
1 npm run watch will call both custom scripts and run them at the same time. This will create two processes that run independently from each other.
Tip Concatenate multiple scripts with & to run them as one script.

Run any script in your node_modules/.bin directory

Installing any node module that adds it’s own executable script, will be available from projectDir/node_modules/.bin. Let’s say, you need babel for your project and you installed it with npm install babel-cli --save-dev, you can run babel from within your project directory by typing ./node_modules/.bin/babel. That is great, since you don’t have to rely on a global installation of babel.

If you want to run babel as part of a script, you would probably specify the whole path to the babel script:

"scripts": {
    "babel-watch": "./node_modules/.bin/babel -w *.js dist"
}

Since npm adds all executable script to the PATH for the script, you can instead write

"scripts": {
    "babel-watch": "babel -w *.js dist"
}
Tip Don’t specify the full path to a script in your projects node_modules/.bin folder. Use the command without the path.

Thank you very much for reading. If you have any comments or questions, please leave them in the comments below.

Thursday, October 29, 2015

Install ownCloud on Synology NAS DS413

Here is a list of steps required to install ownCloud on a Synology NAS. I have a DS413 and I was able to install ownCloud on it. I don't know about the other Synology models out there. Let me know, if you succeeded to install ownCloud on any other model.

ownCloud is not part of the official Synology packet repository. You need to add the community repository to install packets from there.


  1. Log into the Synology admin site
  2. Open Package Center and open the Settings. Under Package Sources, add http://packages.synocommunity.com/ as a source (see screenshot). Click Ok to confirm the new repository.
  3. In Package Center, refresh the list of available packets by pressing the Refresh button at the top of the window
  4. Now search for MariaDB and install it. This is required to install Owncloud. Otherwise, the installation of ownCloud will abort with an error. MariaDB is a fork of MySQL and is one of two databases recommended by ownCloud. The other one is PostgreSQL.
  5. Next enable Web Station in the Control Panel. ownCloud is a webapp and needs the http server to properly work.
  6. Before we continue with the ownCloud installation, you need to create a new shared folder. The installation of ownCloud failed in the beginning, because this folder is required, but could not be created.
  7. Open the Control Panel and open Shared Folder. Create a new shared folder and give it the name ownCloud (this is the default during the ownCloud installation).
  8. Check off Hide this shared folder in "My Network Places". Nobody should modify any content in this directory. This belongs to the ownCloud installation!
  9. Change the permissions of the newly created shared folder. In order to grant ownCloud read/write permissions, select http from the Local Groups (in the Dropdown list on the left hand side above the table) and check the box in the Read/Write column. Press the OK button when done.
  10. Now search for ownCloud and install it.
  11. During the installation of ownCloud, you will be asked to enter the password for the root user. Leave this field empty. By default there root password is not set (this is not secure at all, but for demo purposes, this should be alright)
  12. After ownCloud was installed properly, click on the URL in the ownCloud overview page in the Package Center. In my case it's http://192.168.1.22/owncloud.
  13. Now you will be greeted with ownCloud's login page. Type in your admin password and log into your ownCloud installation. The administration is part of another blog post.

Summary

This is a list of steps to install ownCloud on a Synology NAS DS413. The steps cover the installation of dependencies required to run ownCloud. The administration of ownCloud is not part of this post.
I hope this will help anyone to successfully install ownCloud. Let me know if you have any questions or other constructive feedback.

Tuesday, June 9, 2015

Simple date math in bash script


To catch up with my blog, I needed to extract data from a twitter feed. Usually I update the blog on a weekly basis. Since I didn’t find the time recently, I fell behind.
I was looking for a quick solution to download all the feed data at once. A bash script should be good enough.
The script that I use to extract the data from the twitter feed, expects a date argument in the form mm/dd/yyyy. The script will extract all data for the range [date - 7days, date]

Create the series of dates

I need to create a series of dates for several weeks. Given a start date, I’m going to produce new dates with a 7 day interval. The starting date is included in the series. Here is what I ended up with:
#!/usr/bin/env bash

set -e

# startdate in the form mm/dd/yyyy
startDate=$1
weeks=$2

for ((i=0;i<${weeks};i++)); do
    offsetDays=$((${i}*7))
    newDate=`date -j -v+${offsetDays}d -f "%m/%d/%Y" ${startDate} "+%m/%d/%Y"`

    startDateFilename=`echo ${newDate} | sed "s/\//-/g"`

    echo ${startDateFilename}
    # download the twitter data and redirect all output to that file
    exec &> weeklyTwitterData-${startDateFilename}.txt
    # call the script to extract the data from twitter stream
    coffee src/WeeklyStats.coffee -n ${startDate}
done

Since I didn’t want to do all the calendar math myself, I rely on the magic of the date utility. The line defining newDate is where the magic happens. Parsing a date ${startDate} in a given format %m/%d/%Y, adding $offsetDays to the parsed date and print out the new date in the format %m/%d/%Y.
That’s it.

Wednesday, May 6, 2015

Electron mystery on OSX solved

Do I look like an idiot? I don't know. But I felt like one for the last 2 days.


2 days ago I started to look into on a great project idea, to replace the Brackets Shell with Electron. Great idea! I wanted to contribute and fix issues that crossed my way. But, I followed the given instruction to clone the repo and setup all dependencies. After everything was download and in the right place, I ran npm start to bring up Brackets in it's new electron shell. But that first attempt failed with this error:
> Brackets@1.3.0-0 start ~/develop/fun/OSS/brackets-electron
> electron .

~/develop/fun/OSS/brackets-electron/app/shell-config.js:13
r CONFIG_PATH = path.resolve(utils.convertWindowsPathToUnixPath(app.getPath("u
                                                                    ^
TypeError: app.getPath is not a function
    at Object.<anonymous> (~/develop/fun/OSS/brackets-electron/app/shell-config.js:13:71)
    at Module._compile (module.js:418:26)
    at Object.Module._extensions..js (module.js:436:10)

I was wondering, if there was something important missing in the setup instruction, I simply made a mistake or my system config was tricking me. After checking with the guys who started that effort, I was left with this weird error.

I started to research and looked for others having the same issue, but I couldn't find anything. Okay, it has to be my machine setup. Back at home, I started to setup everything on another machine to see if it works there. The result was the same! The error showed up on a different Macs, with a different OSX versions.

I went back to our slack channel and carefully mentioned, that I'm still not able to get it running yet. Someone replied, that I can install Electron globally and try it again. But this turned out to be a red herring. Nothing has changed and it was really frustrating, since nobody else seemed to have these issues on OSX. I promised them to help, but I could even review and test pull requests.

I did some more research and came across this great blogpost from Thorstenhans. He provided a boilerplate project for an app that uses Electron. I was so happy. I followed his instructions to create a clean app. Everything went fine and I was excited because it's using es6. Unfortunately, the result with Electron was the same.

I left a comment for the blogpost asking, if he has encountered this issue before. Nothing worked for me as expected. So, it must be my machine I concluded. But two machines at the same time?

I mentioned my inability to launch Electron on OSX, briefly in the slack channel for electron-brackets. I felt like an idiot at this point. Somebody who distracts everybody with some nonsense. Nobody had an idea what might help to resolve this misery to help me getting started.

Since the electron-brackets version on Linux seemed to work fine, I decided to pull my Linux VM out of the drawer and give it a try. I cloned the repo, installed everything and typed npm start at the console. Guess what? It worked! I was happy. That is awesome and I'm finally able to help.

But I wasn't happy that my day-to-day machine didn't play well with me. I had a conversation with Thorsten Hans (look at the comments here). He solved another mystery for himself along the way, but I didn't make any progress.

Long story short, I started to get rid of my nodejs installation, install nvm from scratch and hoped to resolve the issue. No luck. But then I inspected the environment variables for anything nodejs related and I found NODE_PATH. It seemed somehow messed up. This post recommended to undef NODE_PATH to solve another issue. But it helped me too. npm start is finally working and the biggest mystery, that let me look like an idiot was resolved.

Thanks

To Thorstenhans for the back and forth to help me resolve the issue. Thanks to Andrew MacKenzie to mention often enough, that the Linux version is doing a good job for him.

Friday, January 2, 2015

Something I Learnt About sed

Note: I’m writing this down to remind myself for the next time I’m using sed and any kind of regex.

I was working on some very simple task: replace a string in a file with a different string.
All of this should happen on our build machine during the product build. Nothing too fancy. But then I got bitten by different versions of sed available on the build machines.
We build our product on OSX, Windows and Linux and I had to realize, that the regex I used, didn’t work with every sed version on the build machines.

My Regex Confusion

To make it clear: I’m not a regex guru. I use it for simple things. When it get’s complex, I usually consult some tools like regex101.com to get it right.
I started with this simple regex to replace the number after the - (the number of commits). The buildnumber looks like 1.0.0-12345.
Here is the command I started with
`cat build.prop | sed "s/(brackets_build_version=\d+.\d+.\d+-)(\d+)/\1${NEW_COMMITS}/" > build.prop.new`.
The result:
`sed: 1: "s/(brackets_build_versi ...": \1 not defined in the RE`
Okay, that doesn’t help that much. After some research I have found the solution: -E needs to be added to the command.
Okay, that error went away, but the replace didn’t work either. Hm, now I had to debug the Regex and find the issue.
After several rounds of experimentation, I started to read the documentation for re_format. That explained a lot: there are modern RE and obsolete RE (they are sometimes referred to as Basic Regular Expression (BRE) and Extended Regular Expression (ERE)), that mainly exist for backward compatibility. They are not as powerful as the modern RE and lack some features.
The last working version looked like:
`cat build.prop | sed -E "s/(brackets_build_version=[[:digit:]]+.[[:digit:]]+.[[:digit:]]+)-([[:digit:]]+)/\1-${COMMITS}/"`
This worked! Heureka.
But wait, why do I have to used [[:digit:]] instead of the much shorter \d+? I don’t know and probably I will never find out. 

Deploy on Build Machines

Happy, that I finally found a solution that worked on OSX. I totally forgot about the other OSses. Once I made the changes and started the build, it failed on Linux and Windows.
WTH? What was I missing? Why doesn’t it even work on Linux? Quickly started my Linux VM and gave it try. The solution was simple: I had to call sed with -r in order to make it work.

Conclusion or What I have Learnt

sed behaves differently on different OS versions. This is probably no exciting news, but I thought I keep this as a reminder for myself.
Using bash or some derivative of it like cygwin or gitbash on Windows does make a difference for some tools. Especially sed comes in two variants: BSD and GNU.
OSX uses BSD and I guess linux and cygwin come with GNU. They might have different command line switched for the same option. So be careful and testing is always required.
Another difference is the Regex engine tha can be used. sed supports basic regular expressions (BRE’s) and extended (ERE or modern) regular expressions
As I mentioned bofore, enabling the extended regular expressions you need to call sed -E on OSX and sed -r on Linux and cygwin.

Sunday, March 3, 2013

Using cobertura with gradle

I wanted to get code coverage for my current groovy project. Since I use gradle and all of my source is written in groovy, I searched for a gradle plugin that provides cobertura functionality for groovy files. I found two (perhaps there are a more available)

Using both plugins wasn’t a big deal. There is a slight difference how to set them up in your build.gradle file though. Both plugins provide very similar configuration options to tweak cobertura’s behavior. Let’s take a look.

Using Eric Wendelin’s Cobertura plugin

Adding the plugin to the build.gradle

I’m using gradle 1.4 for this exercise and I added the following to my build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "net.saliman:gradle-cobertura-plugin:1.1.0"
    }
}

apply plugin: 'cobertura

This will provide you with four new tasks:

  • coberturaInstrumentMain
  • coberturaInstrumentTest
  • testCoberturaReport
  • coberturaConfigureTest

So, which task to call to determine the code coverage? Simply run the test tasks and your source will be instrumented prior to executing your tests.

But what you really want, is to run the check tasks because this will not only run your tests on your previously instrumented source, but it will also create the coverage report. And that’s basically what we want.

The plugin provides some configuration options to tweak cobertura’s behavior

option description
format ’html’ (default) or ’xml’
reportsDir Path to report directory for coverage report. Defaults to ${project.reportsDir.path}/cobertura
includes List glob paths to be reported on. Defaults to [‘**/*.java', ‘**/*.groovy', ‘**/*.scala’]
excludes List glob paths to exclude from reporting. Defaults to [‘**/*Test.java', '**/*Test.groovy', '**/*Test.scala’]
ignores List regexes of classes to exclude from instrumentation. Defaults to [‘org.apache.tools.*', 'net.sourceforge.cobertura.*’]

To specify the output format of cobertura’s coverage report you have to do this:

cobertura {
    format = ‘xml’
}

Using Steve Saliman’s Cobertura plugin

This plugin is based on the work of gradle_cobertura. The original version had some issue with the latest gradle version, so I decided to pick one of the 20 forks. The one with the most recent changes was Steve Saliman’s Cobertura plugin. You can find the setup instructions in the README. Currently the compatibility chart shows that gradle 1.1 is the highest supported version right now. I’m using it with gradle 1.2, 1.3 and 1.4 and they work too. So, let’s move ahead and give it a try.

Adding the plugin to the build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "net.saliman:gradle-cobertura-plugin:1.1.1"
    }
}
apply plugin: 'cobertura'

This will add 2 new tasks:

  • cobertura
  • instrument

To get your coverage report you need to run the cobertura task and the report will be created.

There are a couple of options available to this plugin to change the cobertura behavior:

option description
coverageDirs Directories under the base directory containing classes to be instrumented. Defaults to ${project.sourceSets.main.classesDir.path}
coverageDatafile Path to data file to use for Cobertura. Defaults to ${project.buildDir.path}/cobertura/cobertura.ser
coverageReportDir Path to report directory for coverage report. Defaults to ${project.reportsDir.path}/cobertura
coverageFormats Formats of cobertura report. Default is a single report in ‘html’ format
coverageSourceDirs Directories of source files to use. Defaults to ${project.sourceSets.main.java.srcDirs]
coverageIncludes List of include patterns
coverageExcludes List of exclude patterns
coverageIgnores List of ignore patterns

Fix broken links in coverage report

In order to have a working link to the groovy source files in the coverage report, it’s necessary to add the following to your build.gradle. This will add the groovy source directory to the list of coverageSourceDirs

cobertura {
    coverageSourceDirs << project.sourceSets.main.groovy.srcDirs
}

Report location

For both plugins, the generated report can be found in build/reports/cobertura.

Summary

I have to admit, that both plugins are too similar in functionality to declare a clear favorite. In general, both plugins have subtle differences in regards of their configuration. I like that Eric Wendelin’s Cobertura plugin supports groovy (and scala) files right out of the box without further configuration. But this is only a very small advantage. I’ll stick with Steve Saliman’s Cobertura plugin for a while, since there is still active development. Not a strong reason, but as I mentioned earlier, there are only subtle differences between both plugins.

The choice is up to you.

Monday, February 11, 2013

List all available instruments templates

Using Apple's instruments on the command line to inspect an iOS application on the device, usually involves a specific template to capture data from the application running on the device.

For my current project I usually used the Automation.tracetemplate to launch my iOS app. But after I've upgraded Xcode from 4.3 to 4.5, the filesystem location of the instruments templates have been slightly changed. The framework that I wrote for the performance tracking system failed in finding the template. I started to investigate a better solution to be able to deal with different Xcode versions that could be found on the dev machines.

For that reason I created a little helper class to identify the version of Xcode to locate the correct path of the Automation.tracetemplate. That works pretty fine, but I don't know if this will work for future Xcode versions too. This solution required xcodebuild -version to determine the Xcode version and xcode-select -print-path to determine the location of the Xcode folder. I needed this information to assemble the path to the templates.
There must be a better, shorter way of getting this information.

A better solution

Running instruments on the command line produces a rather concise than helpful overview of the available options. I couldn't find any manpage for instruments on my machine. Rather by accident than intentional, I came across the instruments manpage on Apple's Developer Connection website.

The manpage contained far more information about the available options including some description for the unknowing user. I discovered the option -s that produces a list of all available instrument templates.  Even if the manpage was targeting the Xcode tools 3.2.5 version (I couldn't find a more recent version), the option is still recognized by the latest instruments (as time of writing I used Xcode 4.6).

Running instruments -s and parsing the output will give me path to the Automation.template. without any guessing or probing. I hope this option will remain available in instruments in future versions.

Tuesday, July 26, 2011

List all jenkins jobs with a perforce scm configuration

Here is an instruction on how to execute this groovy script on your jenkins instance to display all jobs that use perforce as SCM provider. This was one of the first scripts I wrote to get an idea about the jenkins CLI and how to execute custom scripts. This script can be used to examine your perforce configurations used for your jobs. In my case it was the foundation to change all passwords for certain perforce user.

Prerequisites
You need to have a java installation on your machine and java must be available on your PATH. groovy itself is not required to execute the scripts.
I assume that you have Jenkins running on your machine, so that I refer to localhost to access the Jenkins instance.
  1. If you already have a copy of jenkins-cli.jar on your machine, then skip to step 2. Otherwise open a browser and navigate to this URL http://localhost:8080/cli. Follow the instructions and download the jenkins-cli.jar to a known directory
  2. Open a terminal or command window and change into the directory where your jenkins-cli.jar is located
  3. Type java -jar jenkins-cli.jar -s http://localhost:8080 help. This will output a list of all available commands that this jenkins instance provides.
  4. Okay, now go ahead and save this snippet as listAllProjectsWithPerforceSCM.groovy to the same directory where you previously downloaded the jenkins-cli.jar
  5. Now enter the following on the command line:
    java -jar jenkins-cli.jar -s http://localhost:8080 groovy listAllProjectsWithPerforceSCM.groovy
This will show you something similar to this output:

Job 'Test' uses the following perforce configuration
------------------------------------------------------------------------
P4Port: localhost:1666
P4Client: testbuilder
P4User: testbuilder
P4Password: 0f0kqlwaDeXrEj0PA0z/+IXZM1f8G8QsgBlUgnUv8bbR2bzXLfa3AlrK8xqw==

That's it. There is nothing complicated about this script, but it shows some of the capabilities to automate certain tasks. Take the script as example to play around with it and explore new ways to interact with jenkins.

Thanks for reading this post.

Thursday, July 14, 2011

ConfigSluper, ConfigObject and some stupid bugs

In my last project I wrote some scripts to handle the automatic integration of libraries from different Version Control Systems into our source code repository.
I wrote a script to generate an XML file, that served as input for an existing perl script.

To generate the XML file I used a groovy script which described the dependent components and the revision as well as the platform dependent location in the VCS (which is omitted here).



Processing this file is a pretty straightforward task.



The reason why I'm writing this up, is to tell that I spent a good amount of time, figuring out if there is a bug in the underlying ConfigObject. The ConfigObject is created by ConfigSluper().parse(...) and represents the data in-memory. Since ConfigObject inherits from LinkedHashMap, one can assume (and I really did!), that the semantics are like using a HashMap. But I was wrong! There happens some _magic_, when you do the following:



In my script there was a piece of code that relied on the sub-node count of the Component node. At a certain point, I was really convinced that I found a bug. But that would have been too obvious IMHO, that this kind of misbehavior had slipped through all testcases.
To make a long story short. I did some investigation and found the reason in the implementation of the ConfigObject


You can find the secret (if you will) in line 8. If you access a key in the ConfigObject that doesn't exist, then there will be an empty one created on the fly. This is not really bad, as long as you don't rely on the amount of nodes before and after querying the ConfigObject.

Wednesday, August 4, 2010

Thunderbird SMTP Settings for MobileMe

Finally I figured out what the settings for Thunderbird look like to send e-mails via MobileMe. Despite several other postings and support entries, these are the settings that work on my machine:
SettingValue
Server Namesmtp.me.com
Port25
Authentication methodNormal password
Connection SecuritySTARTTLS

HTH.

Tuesday, June 8, 2010

Strange Compile Error in Flex Builder

Yesterdy I started a small project in Flex Builder. But I was stuck in the middle of the night, since Flex Builder complained about something in my source code. The Problems View in Flex Builder displayed the following error:




Wow, what a precise error message. Right-click for more information brought me to a very generic webpage telling me, that I could have probably found a compiler error. Great! First time ever that I discovered a compiler error. But wait: I bing'ed (can you say this?) for the error message, to see if somebody already reported this. BING! Match. And here we go:

The solution was pretty easy and documented here.

I searched my source code and found this line:

Have you noticed the first "=" instead of the ":"? Lucky you! It took me far too much time to discover this typo.

Fixing this typo and the error went away.

Wednesday, April 7, 2010

MacPorts contribution

3 weeks ago I submitted my first Portfile to the MacPorts Project. You can find it here!
This port provides the xjobs utility to execute jobs in parallel to leverage the power of multi-processor/core machines. It works similar to the xargs tool that you can find on nearly any Un*x based system nowadays.

Thursday, April 9, 2009

Do you know Fluid?

Are you using a lot web based applications these days? Do you have multiple browser windows or tabs open at a time? Is the Mac your preferred working horse? Well, then you should have a look at Fluid. Fluid creates a so called "Site Specific Browser" aka SSB which is a native MacOSX Application.

How does it work? Simply download the provided Application for the Mac (sorry Windows User!) and start it right away. Fluid will open a very simplistic dialog which requires only a few information about the Website you want to convert to a SSB:

So the most important thing in this case is the URL of the Website you want to have as a separate launchable application on your Mac. Providing a distinct name will make things easier to find your SSB on your mac. You can choose the location for your SSB. I think it's a good idea to place it in the Applications folder. You can even provide an Icon for your new App. You can either use the Website's favicon or you can provide your own icon. Note: I tested this with gmail and the Favicon didn't work for me. So I chose the gmail icon from Chris Ivarsons site. There you can find some more Icons for popular Websites. Press the Create button and you're set.

What is created for you? Well, you get a native MacOSX Application with the icon you selected at the location you specified. If you now start this Application the Website from the provided URL will be opened and displayed in the window. Now you can start weaking some of the Preferences for this specific SSB. Below is a screenshot of my GMail SSB.

Usually you can live with the default preferences, but I recommend to step through each section to find out what you can modify with each of these settings. I also recommend a closer look at the website and the community part to find some more tips and tricks on the other available features that could make your life easier. My favorite feature so far is the conversion of the SSB to a MenuExtra SSB. This will relaunch your SSB and create an entry in the system wide status bar at the top of the screen. Now your favorite Website is located right at the top of your screen.
I hope you will like Fluid as much as I do. Have fun!

Thursday, December 11, 2008

Sind Sie ein RSS Feed Junkie?

Was für eine Frage in der heutigen Zeit. RSS Feeds haben sich für eine ganze Menge Mitmenschen zur primären Nachrichtenquelle entwickelt. Das ist ja auch gar nicht so schlecht. Der Konsum von Feeds führt dazu, dass viele Informationen in kurzer Zeit dem Leser zugeführt werden. Die Konsumenten haben so die Möglichkeit sehr schnell die aktuelle politische Nachrichtenlage, Neues aus der IT-Welt und die Updates der vielen Internet-Angebote zu sichten.

Willkommen im digitalen Informationszeitalter!

Das Problem
Die ursprüngliche Frage dieses Posts resultierte aus einem Problem, das ich mit meinem iPhone und dem installierten Feedreader NetNewsWire darauf habe: ich habe einfach zu viele und zu hochfrequente Feeds abonniert! Wenn ich morgens in der Bahn den Feed-Reader starte, dann passiert erstmal nichts. Nach langer Wartezeit wird der Reader meistens beendet (ich führe das auf extremen Speicherverbrauch des Readers zurück). Sollte der Reader dann doch noch Starten und meine Liste mit den Feeds anzeigen, dann bin ich jedesmal ob der unglaublichen Anzahl von 4000-5000! ungelesenen Einträgen wirklich überwältigt. Mir bleibt dann in den meisten Fällen nichts anderes übrig, als viele der Feeds noch schneller zu überfliegen und alle Einträge auf gelesen zu setzen.

Mir ist das erst in den letzten Tagen so bewusst geworden, weil ich nach fast 30 Minuten Zugfahrt fast gar keine Information aus den Feeds gewonnen hatte, da ich mich hauptsächlich um die Reduktion der ungelesenen Feeds und die schlechte Performance des Readers gekümmert habe. Da stellte sich für mich die Sinnfrage nach der Feeds. Wieviele Feeds sind wirklich nötig um genügend wertvolle Informationen zu bekommen? Was ist mit der Qualität der Feeds? Brauchen wir die Feeds wirklich, oder sollte man sich um Informationen aus anderen Quellen bemühen? (das hat evtl. etwas mit mühen, abmühen zutun!). Gibt es eine Möglichkeit die Information zu kondensieren und zu filtern?

Ein paar Daten für die Statistik aus meinem Feed-Reader:
  • 91 abonierte Feeds
  • ca. 6500 ungelese (das ändert sich gleich...)
  • Themengebiete: Nachrichten (deutsch, englisch), Computernews (diverse), Apple (diverse), Web2.0, Produktivität, Programmiersprachen

Die Lösung
Ich glaube nicht, dass es eine allgemeingültige Lösung gibt, die für alle Menschen praktikabel ist. Aber das trifft ja auf die meisten Probleme zu.
Vielleicht geht es aber anderen Menschen da draussen auch so. Um trotzdem eine Lösung (zumindest für mich) parat zu haben und mehr Wert aus dem Angebot zu schöpfen, habe ich mich entschlossen zwei Dinge zu tun:
  1. Qualität vor Quantität! Die Anzahl der Feeds auf ca. 30! zu reduzieren
  2. Yahoo-Pipes benutzen um mehrere Feeds zusammenzuführen und zu filtern um einen neuen Feed zu erzeugen (macht bei bestimmten Themen Sinn)
Ich bin anscheinend ein RSS Feed Junkie. Ja, aber die Erkenntnis dessen, ist der erste Weg zur Besserung.
In diesem Sinne bis zum nächsten Feed.

, ,

Tuesday, October 7, 2008

Improve your productivity

My main profession is to write software. Typing on keyboards is essential as well as moving the mouse around to point and click.
Since my early days in this industry I like to learn the "essential" keyboard shortcuts for every software I use on a daily basis. Learning the "right" shortcuts will improve your working speed and therefore the overall productivity, since you don't need to switch between keyboard and mouse that often.
I use Eclipse for my daily work a lot. Lately I found a plug-in called MouseFeed which helps me to improve my knowledge of shortcuts even further.
What is the plug in supposed to do? Well, basically for every function that you use the mouse for and there is a corresponding keyboard shortcut available, it'll show up a little yellow popup dialog with the shortcut to remember. This is pretty neat and helps you to remember the shortcut and avoids the usage of the mouse.

Friday, September 12, 2008

TubeTV und Perian

Heute brauchte ich eine einfache Lösung um ein Flash Video (Suffix flv) in einen QuickTime Movie (Suffix mov) zu überführen, um ihn auf meinem iPhone auf dem Weg zur Arbeit ansehen zu können. Nachdem ich einige sehr Mac Affine Kollegen gefragt habe und niemand eine kostengünstige Lösung hatte, habe ich mich selber auf die Suche begeben. Das Ergebnis war TubeTV. Das war genau was ich gesucht habe. Einfach und kostenlos.
Also schnell die Software auf meinen Rechner geladen und los ging's. Beim ersten Start von TubeTV kommt ein Hinweis, dass noch Perian installiert werden muss. Perian erweitert QuickTime damit unterschiedliche Video Formate von QuickTime verarbeitet werden können.

Nachdem ich Perian installiert hatte, konnte TubeTV seine Arbeit aufnehmen. Also hab ich mein 150 MB Flash Video in kurzer Zeit in ein iPhone taugliches QuickTime Video konvertiert. So hab ich mir das vorgestellt.

Wichtig: Bei Perian und TubeTV handelt es sich um kostenlose Software. Um eine Weiterentwicklung sicherzustellen, würden sich die Entwickler über kleine Spende via PayPal freuen.

Technorati Tags: , , ,

Tuesday, August 26, 2008

Superscript und Subscript mit LaTex

Heute habe ich einen Brief mit LaTex geschrieben und musste einen Buchstaben als Subscript setzen. Ich wußte zwar wie das bei Formeln gemacht wird, aber im "normalen" Text war mir das leider nicht geläufig.

Hier also die Lösung:


  • Subscript: $_TextDerAlsSubscriptErscheinenSoll$

  • Superscript: $^TextDerAlsSuperscriptErscheinenSoll$


Gar nicht so schwierig.


Technorati Tags:
, ,