text: #' Unloads package(s)
  #' 
  #' Unloads package(s) or all packages.
  #' 
  #' @param \dots name of package(s) or "all" (all removes all add on packages).
  #' @param negate logical. If \code{TRUE} will unload
  #' all add on packages except those provided to \code{p_unload}.
  #' @param char Character vector containing packages to load.  If you are calling
  #' \code{p_unload} from within a function (or just having difficulties calling it 
  #' using a character vector input) then pass your character vector of packages 
  #' to load to this parameter directly.
  #' @param character.only logical. If \code{TRUE} then \code{p_unload} will only 
  #' accept a single input which is a character vector containing the names of 
  #' packages to load.
  #' @note \code{p_unload} will not unload the base install packages that load 
  #' when R boots up.  See the comments in the help for \code{detach} about some 
  #' issues with unloading and reloading namespaces.
  #' @seealso \code{\link[base]{detach}}
  #' @keywords detach package
  #' @export
  #' @examples
  #' \dontrun{
  #' p_load(lattice)
  #' p_loaded()
  #' p_unload(lattice)
  #' p_loaded()
  #' 
  #' p_load("lattice", "MASS")
  #' p_loaded()
  #' p_unload(all)
  #' p_loaded() # will not work as you unloaded pacman
  #'
  #' library(pacman)
  #' p_load(lattice, MASS, foreign)
  #' p_loaded()
  #' p_unload(pacman, negate=TRUE)
  #' p_loaded()
  #' }
  p_unload <- 
  function (..., negate = FALSE, char, character.only = FALSE) {
  	
      if(!missing(char)){
          toUnload <- char
      }else if(character.only){
          toUnload <- eval(match.call()[[2]])
      }else{
          toUnload <- tryCatch(as.character(match.call(expand.dots = FALSE)[[2]]), error=function(err) NA)
      }
  
      loaded <- names(utils::sessionInfo()[["otherPkgs"]])
      defaultPackages <- getOption("defaultPackages")
      cantUnload <- c("base", defaultPackages)
      if (negate & !any(toUnload %in% "all")) {
          toUnload <- loaded[!loaded %in% toUnload]
      }
      
      # Either not loaded or a base package
      toUnloadButNotLoaded <- toUnload[!toUnload %in% c(loaded, "all")]
      # default packages
      toUnloadButCantUnload <- toUnloadButNotLoaded[toUnloadButNotLoaded %in% cantUnload]
      # Told to unload but they aren't actually loaded
      toUnloadButNotLoaded <- toUnloadButNotLoaded[!toUnloadButNotLoaded %in% cantUnload]
  
      mt <- toUnload %in% "all"
      toUnload <- toUnload[toUnload %in% loaded]
      if (!identical(mt, logical(0)) & all(mt)) {
          toUnload <- names(utils::sessionInfo()[["otherPkgs"]])
          x <- paste0("package:", toUnload)
          toUnload <- paste(toUnload, collapse = ", ")
          invisible(lapply(x, function(package) {
              suppressWarnings(detach(package, character.only = TRUE, 
                                      force = TRUE, unload = TRUE))
          }))
      } else {
          unload <- function(packageToUnload) {
              x <- paste0("package:", packageToUnload)
              suppressWarnings(detach(x, unload = TRUE, character.only = TRUE, 
                                      force = TRUE))
          }
          invisible(lapply(toUnload, unload))
      }
      
      ## Print messages about what was done
      if (!identical(toUnloadButCantUnload, character(0))) {
          message(paste0("The following packages are a base ", 
                         "install and will not be unloaded:\n"), 
                  paste0("\b", paste(toUnloadButCantUnload, collapse = ", ")), 
                  "\n\n")
      }
      if (!identical(toUnloadButNotLoaded, character(0))) {
          message("The following packages were not previously loaded:\n", 
                  paste0("\b", paste(toUnloadButNotLoaded, collapse = ", ")), 
                  "\n\n")
      }
      if (length(toUnload) > 0) {
          message("The following packages have been unloaded:\n",
                  paste0("\b", paste(toUnload, collapse = ", ")), 
                  "\n")
      }
  }
  