diff --git a/commands/core/core.drush.inc b/commands/core/core.drush.inc
old mode 100644
new mode 100755
index 429bb25..7fafb96
--- a/commands/core/core.drush.inc
+++ b/commands/core/core.drush.inc
@@ -1150,3 +1150,23 @@ function drush_core_execute() {
   // Must be a local command.
   return drush_shell_proc_open($cmd);
 }
+
+/**
+ * Implements hook_drush_output_formats().
+ */
+function core_drush_output_formats() {
+  $formats['export'] = array(
+    'label' => dt("Export"),
+    'callback' => 'drush_output_format_export',
+  );
+  $formats['json'] = array(
+    'label' => dt("JSON"),
+    'callback' => 'drush_output_format_json',
+  );
+  $formats['print_r'] = array(
+    'label' => dt("print_r"),
+    'callback' => 'drush_output_format_print_r',
+  );
+
+  return $formats;
+}
diff --git a/commands/core/scratch.php b/commands/core/scratch.php
index afd413a..73ea0a2 100644
--- a/commands/core/scratch.php
+++ b/commands/core/scratch.php
@@ -16,5 +16,5 @@
  */
 
 // Just some ideas to get the juices flowing.
-drush_print_r(user_roles());
-drush_print_r($GLOBALS['user']);
+drush_print(drush_format(user_roles()));
+drush_print(drush_format($GLOBALS['user']));
diff --git a/commands/runserver/runserver-drupal.inc b/commands/runserver/runserver-drupal.inc
index d860580..3e05d6e 100644
--- a/commands/runserver/runserver-drupal.inc
+++ b/commands/runserver/runserver-drupal.inc
@@ -94,7 +94,7 @@ class DrupalServer extends HTTPServer {
       }
     }
     if ($this->debug) {
-      drush_print_r($request);
+      drush_print(drush_format($request));
     }
   }
 }
diff --git a/commands/sql/sql.drush.inc b/commands/sql/sql.drush.inc
index 3200cdb..10f260e 100644
--- a/commands/sql/sql.drush.inc
+++ b/commands/sql/sql.drush.inc
@@ -44,12 +44,13 @@ function sql_drush_command() {
     'topics' => array('docs-policy'),
   );
   $items['sql-conf'] = array(
-    'description' => 'Print database connection details using print_r().',
+    'description' => 'Print database connection details.',
     'hidden' => TRUE,
     'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION,
     'options' => array(
       'all' => 'Show all database connections, instead of just one.',
       'show-passwords' => 'Show database password.',
+      'format' => 'Available output formats are: ' . implode(', ', array_keys(drush_format_get_output_formats())),
     ) + $options,
   );
   $items['sql-connect'] = array(
@@ -218,7 +219,7 @@ function drush_sql_conf() {
   if (!drush_get_option('show-passwords', FALSE)) {
     drush_unset_recursive($db_spec, 'password');
   }
-  drush_print_r($db_spec);
+  drush_print(drush_format($db_spec));
   return $return;
 }
 
diff --git a/commands/user/user.drush.inc b/commands/user/user.drush.inc
index a1519bc..4ea46b3 100644
--- a/commands/user/user.drush.inc
+++ b/commands/user/user.drush.inc
@@ -33,6 +33,7 @@ function user_drush_command() {
     'options' => array(
       'full' => 'show extended information about the user',
       'short' => 'show basic information about the user (this is the default)',
+      'format' => 'Available output formats are: ' . implode(', ', array_keys(drush_format_get_output_formats())),
     ),
   );
   $items['user-block'] = array(
@@ -517,7 +518,7 @@ function _drush_user_print_info($uid) {
     foreach($userinfo as $key => $val) {
       if (is_array($val)) {
         drush_print($key . ': ');
-        drush_print_r($val);
+        drush_print(drush_format($val));
         $userinfo_pipe[] = '"' . implode(",", $val) . '"';
       }
       else {
diff --git a/docs/drush.api.php b/docs/drush.api.php
old mode 100644
new mode 100755
index 50e5c96..9903c81
--- a/docs/drush.api.php
+++ b/docs/drush.api.php
@@ -318,3 +318,23 @@ function hook_drush_engine_ENGINE_TYPE() {
 /**
  * @} End of "addtogroup hooks".
  */
+
+/**
+ * Register format types with drush to be used by drush_format().
+ *
+ * - label - The format label.
+ * - callback - The callback function to be used to process this format.
+ *   This function is passed $input and $label.
+ *   @see core_drush_output_formats() and related callback functions in output.inc file.
+ *
+ * @see drush_format().
+ *
+ */
+function hook_drush_output_formats() {
+  $formats['print_r'] = array(
+    'label' => dt("print_r"),
+    'callback' => 'drush_output_format_print_r',
+  );
+
+  return $formats;
+}
diff --git a/includes/drush.inc b/includes/drush.inc
index 546b2c1..dca0e25 100644
--- a/includes/drush.inc
+++ b/includes/drush.inc
@@ -1337,7 +1337,7 @@ function dlm($object) {
 function drush_pipe_output() {
   $pipe = drush_get_context('DRUSH_PIPE_BUFFER');
   if (!empty($pipe)) {
-    drush_print_r($pipe);
+    drush_print(drush_format($pipe, NULL, 'print_r'));
   }
 }
 
diff --git a/includes/output.inc b/includes/output.inc
old mode 100644
new mode 100755
index f036e34..e681329
--- a/includes/output.inc
+++ b/includes/output.inc
@@ -61,15 +61,6 @@ function drush_print_pipe($message = '') {
 }
 
 /**
- * Prints an array or string.
- * @param $array
- *   The array to print.
- */
-function drush_print_r($array, $handle = NULL) {
-  drush_print(print_r($array, TRUE), 0, $handle);
-}
-
-/**
  * Prepares a variable for printing.
  * @param mixed $input
  *   A variable.
@@ -79,46 +70,92 @@ function drush_print_r($array, $handle = NULL) {
  *   The variable formatted according to specified format. Ready for drush_print().
  */
 function drush_format($input, $label = NULL, $format = NULL) {
+  $formats = drush_command_invoke_all('drush_output_formats');
+
   if (is_null(($format))) {
     $format = drush_get_option('format', 'print_r');
   }
-  if ($format != 'export') {
-    if ($input === TRUE) {
-      $input = 'TRUE';
+
+  // Contruct the output as defined by the formatter.
+  if (isset($formats[$format]['callback']) && function_exists($formats[$format]['callback'])) {
+    $function = $formats[$format]['callback'];
+  }
+  else {
+    // Display the formatter error only once.
+    static $error = FALSE;
+    if (!$error) {
+      drush_set_error('DRUSH_FORMAT_NOT_FOUND',
+        dt("Format !format not found. Using 'print_r' instead.", array('!format' => $format)));
+      $error = TRUE;
     }
-    elseif ($input === FALSE) {
-      $input = 'FALSE';
+    $function = $formats['print_r']['callback'];
+  }
+
+  return $function($input, $label);
+}
+
+/**
+ * return an array of available formats.
+ */
+function drush_format_get_output_formats() {
+  $formats = drush_command_invoke_all('drush_output_formats');
+  $list = array();
+
+  foreach ($formats as $name => $format) {
+    $list[$name] = $format['label'];
+  }
+
+  return $formats;
+}
+
+/**
+ * Prints an array or string.
+ * @param $input
+ *   The array or string to print.
+ */
+function drush_output_format_print_r($input, $label = NULL) {
+  if (is_string($input)) {
+    $input = '"' . $input . '"';
+    if ($label) {
+      $input = $label . ': ' . $input;
     }
   }
+  elseif (is_array($input) || is_object($input)) {
+    if ($label) {
+      $input = array($label => $input);
+    }
+  }
+  return print_r($input, TRUE);
+}
 
-  switch ($format) {
-    case 'export':
-      if ($label) {
-        $output = "\$variables['$label'] = " . var_export($input, TRUE) . ';';
-      }
-      else {
-        $output = var_export($input, TRUE);
-      }
-      break;
-    case 'json':
-      $output = drush_json_encode($input);
-      break;
-    case 'print_r':
-    default:
-      if (is_string($input)) {
-        $input = '"' . $input . '"';
-      }
-      elseif (is_array($input) || is_object($input)) {
-        $input = print_r($input, TRUE);
-      }
+/**
+ * Formats variables using var_export.
+ */
+function drush_output_format_export($input, $label = NULL) {
+  if ($input === TRUE) {
+    $input = 'TRUE';
+  }
+  elseif ($input === FALSE) {
+    $input = 'FALSE';
+  }
 
-      if ($label) {
-        $input = $label . ': ' . $input;
-      }
-      $output = $input;
-      break;
+  if ($label) {
+    return "\$variables['$label'] = " . var_export($input, TRUE) . ';';
+  }
+  else {
+    return var_export($input, TRUE);
+  }
+}
+
+/**
+ * Formats variables with JSON.
+ */
+function drush_output_format_json($input, $label = NULL) {
+  // JSON can display the label as the key in an associative array.
+  if ($label) {
+    $input = array($label => $input);
   }
-  return $output;
+  return drush_json_encode($input);
 }
 
 /**
