This is my code to using monitor change folder:
WatchService watcher = FileSystems.getDefault().newWatchService();
Path dir = Paths.get("/home/user/test/");
dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
System.out.println("Begin monitor to test folder: ");
for (;;) {
// wait for key to be signaled
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
// The filename is the
// context of the event.
#SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path filename = ev.context();
if (filename.toString().startsWith(".")) continue;
if (kind == OVERFLOW) {
continue;
} else if (kind == ENTRY_CREATE) {
System.out.println(kind.name() + ":" +filename);
} else if (kind == ENTRY_DELETE) {
System.out.println(kind.name() + ":" +filename);
} else if (kind == ENTRY_MODIFY) {
System.out.println(kind.name() + ":" +filename);
}
}
boolean valid = key.reset();
if (!valid) {
break;
}
}
It's great on windown, Mac os, However when run on ubuntu 16.04, I to face the problem:
For existed files in watched folder: when I edit a file then I receiver create event, While i want to get modify event
Please help me
Thanks.
Make sure that the program you're using to edit the file with in Ubuntu doesn't create a hidden file. Some editors do this to make sure no changes are lost when the program crashes.
So make sure that your editor does not create a hidden file when you're editing the file and if it does use another program or handle the hidden "subfile".
Related
I am trying to make slight modification at line 5 of below After Effects expression. Line 5 checks if the layer is visible and active but I have tried to add an extra check that the layer should not be a comp item. (In my project, layers are either text or image layer and I beileve an image layer means a comp item). Somehow the 'instanceof' method to ensure that layer should not be a comp item is not working. Please advise how to fix this error, thanks.
txt = "";
for (i = 1; i <= thisComp.numLayers; i++){
if (i == index) continue;
L = thisComp.layer(i);
if ((L.hasVideo && L.active) && !(thisComp.layer(i) instanceof CompItem)){
txt = i + " / " + thisComp.numLayers + " / " + L.text.sourceText.split(" ").length;
break;
}
}
txt
While compItem is available only in ExtendScript, you can actually check the properties available in the {my_layer}.source object.
Here's a working example (AE CC2018, CC2019 & CC2020): layer_is_comp.aep
The expression would be something similar to:
function isComp (layer)
{
try
{
/*
- used for when the layer doesn't have a ['source'] key or layer.source doesn't have a ['numLayers'] key
- ['numLayers'] is an object key available only for comp objects so it's ok to check against it
- if ['numLayers'] is not found the expression will throw an error hence the try-catch
*/
if (layer.source.numLayers) return true;
else return false;
}
catch (e)
{
return false;
}
}
try
{
// prevent an error when no layer is selected
isComp(effect("Layer Control")(1)) ? 'yes' : 'no';
}
catch (e)
{
'please select a layer';
}
For your second question, you can check if a layer is a TextLayer by verifying that it has the text.sourceText property.
Example:
function isTextLayer (layer)
{
try
{
/*
- prevent an expression error if the ['text'] object property is not found
*/
var dummyVar = layer.text.sourceText;
return true;
}
catch (e)
{
return false;
}
}
You're mixing up expressions and Extendscript. The compItem class is an Extendscript class and I'm pretty sure that it isn't available for expressions.
I'd suggest reading the docs: https://helpx.adobe.com/after-effects/user-guide.html?topic=/after-effects/morehelp/automation.ug.js
I am trying to write a tool to compare my files but I found it difficult to interactive with. I want to support 2 operations: 1) load my files into memory 2) compare the files already loaded.
The idea is like below
while (true) {
getline(&line, &linesize, stdin);
if (strlen(line) < 2) continue;
token = strtok(line, DELIM);
if (!strcmp(token,"load")) {
puts("you want to load something");
} else if (!strcmp(token, "compare")) {
puts("you want to compare something");
} else if (!strcmp(token, "exit")) {
puts("exiting...");
exit(1);
} else {
puts("Cannot parse, try again");
}
}
In terminal, if I want to compare some MyVeryLongFileNameFile.foo and AnotherVeryLongFileNameFile.bar, I can just type diff My\tab Ano\tab \enter and it will auto completes the filenames for me.
I would like to also have these kind of features in my program, like using tab to autocomplete, using up/down to choose from previous commands, etc. How should I achieve this?
Using the ncurses.h library help you accomplish this.
I'm trying to save a Location in a config.yml, and when he steps onto that location, it provokes an action. However, that is not happening.
Sorry for including the entire code, but I thought it would be essential for this kind of program.
Main class:
public class Turrets extends JavaPlugin{
ArrayList<String> playersThatShouldPlaceBlock = new ArrayList<String>();
HashMap<String, String> turretName = new HashMap<String, String>();
String turretsMsg = ChatColor.RED + "[" + ChatColor.GOLD + "Turrets" + ChatColor.RED + "]" + ChatColor.GOLD + ": ";
public int waitForPlacement;
public void loadConfig() {
this.getConfig().addDefault("Turrets.", null);
this.saveConfig();
}
public void onEnable(){
new CreateTurretEvent(this);
loadConfig();
}
public void onDisable(){
loadConfig();
}
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
final Player p = (Player) sender;
if (cmd.getName().equalsIgnoreCase("turret")){
if (args.length < 2){
p.sendMessage(turretsMsg + ChatColor.RED + "Invalid usage! /turret [create or delete] [name]");
return true;
}
else if (args.length >= 2){
if (args[0].equalsIgnoreCase("create")){
if (args[1] != null){
p.sendMessage(turretsMsg + ChatColor.GOLD + "Place a block and YOU will become a turret when you step on it!");
playersThatShouldPlaceBlock.add(p.getName());
turretName.put(p.getName(), args[1]);
waitForPlacement = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
#Override
public void run() {
p.sendMessage(turretsMsg + ChatColor.RED + "You waited too long so the action was cancelled!");
playersThatShouldPlaceBlock.remove(p.getName());
}
}, 600L);
return true;
}
}
}
}
return false;
}
}
Listener class:
package me.mortadelle2.turrets;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerMoveEvent;
public class CreateTurretEvent implements Listener{
Turrets getter;
public CreateTurretEvent(Turrets plugin){
plugin.getServer().getPluginManager().registerEvents(this, plugin);
getter = plugin;
}
#EventHandler
public void playerPlacesBlockToBecomeTurret(BlockPlaceEvent e){
Player p = e.getPlayer();
if (getter.playersThatShouldPlaceBlock.contains(p.getName())){
p.sendMessage(getter.turretsMsg + "That block is now turretified!");
getter.getServer().getScheduler().cancelTask(getter.waitForPlacement);
getter.playersThatShouldPlaceBlock.remove(p.getName());
Location blockLocation = e.getBlock().getLocation();
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName()), blockLocation);
}
}
#EventHandler
public void playerStepsOnTurret(PlayerMoveEvent e){
Player p = e.getPlayer();
if (getter.getConfig().contains("test")){ //I will add something more specific than test later
p.sendMessage("This is a test");
}
}
}
Problem 1: spelling mistake (this problem has been edited out of the question at question revision 3)
You seem to have misspelled onDisbale(){. When a plugin is disabled, it will run the method onDisable() on your plugin. In your case it isn't run because you don't have a method with that exact signature.
How to prevent this in the future
By added #Override at the start of a method, you are saying that it MUST override a existing method found in a parent class. This can be used like:
#Override
public void onDisable() {
Problem 2: Implementation of the PlayerMoveEvent isn't finished yet
Notice, stackoverflow isn't a "we write code for you service"
By analyzing your code, you are saving your config in the following format:
playername:
turretname: (location object)
Step 1: changing the location saving
The bukkit configuration doesn't work properly with Location objects, you should change your location saving to
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".world", player.getLocation().getWorld().getName());
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".x", player.getLocation().getBlockX());
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".y", player.getLocation().getBlockY());
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".z", player.getLocation().getBlockZ());
This changes the configuration to store the world, x, y and z seperately
Step 2: parsing the config at the PlayerMoveEvent
Because we changed our config format, it will be easier to detect what turret we are standing on at the PlayerMoveEvent
We will the following method of detecting what block we are standing on at the PlayerMove
Check if the turret exists inside the configuration
ConfigurationSection sec = getter.getConfig().getConfigurationSection("Turrets."+getter.turretName.get(p.getName()));
// Todo: check if the player exists inside getter.turretName
if(sec != null){
....
}
Parse the configuration to check if the location is found
Location loc = event.getPlayer().getLocation();
if(loc.getBlockX() == sec.getInt("x") && loc.getBlockY() == sec.getInt("y") && loc.getBlockZ() == sec.getInt("z") && loc.getWorld().getName().equals(sec.getString("world"))) {
event.getPlayer().sendMessage("This is a test");
}
This should fix the problem you are having. The following improvements can be done:
Only call the player move code when the player changes the block
Use more descriptive variable names, for example getter should be renamed to main or plugin
I'm struggling with Adobe Air native process communication. I'd like to pass an c++ exe shellcommands stored at processArgs when started. The c++ program uses this arguments to choose device channel and symbolrate of an CAN-Bus-Adapter. The c program itself creates an json database for an html page. While the c program is processing i'd like to get some feedback of the program and if it exits adobe air should create a link for the html page with the function onExit. The c program uses standart output of iostream lib ("cout", "cerr") to send messages to adobe air.
Adobe Air script:
var process;
function launchProcess()
{
if(air.NativeProcess.isSupported)
{
setupAndLaunch();
}
else
{
air.Introspector.Console.log("NativeProcess not supported.");
}
}
function setupAndLaunch()
{
var cpp_device = $( "#device option:selected" ).val();
var cpp_channel= $("#channel option:selected").text();
var cpp_symbolRate= $("#symbolRate option:selected").val();
air.Introspector.Console.log("CHANNEL",cpp_channel);
air.Introspector.Console.log("Device",cpp_device);
air.Introspector.Console.log("Symbol Rate",cpp_symbolRate);
var nativeProcessStartupInfo = new air.NativeProcessStartupInfo();
var file = air.File.applicationDirectory.resolvePath("InteractiveDocumentation.exe");
nativeProcessStartupInfo.executable = file;
var processArgs = new air.Vector["<String>"]();
processArgs.push(cpp_device);
processArgs.push(cpp_channel);
processArgs.push(cpp_symbolRate);
nativeProcessStartupInfo.arguments = processArgs;
process = new air.NativeProcess();
process.start(nativeProcessStartupInfo);
process.addEventListener(air.ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
process.addEventListener(air.ProgressEvent.STANDARD_ERROR_DATA, onErrorData);
process.addEventListener(air.IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOError);
process.addEventListener(air.IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError);
process.addEventListener(air.NativeProcessExitEvent.EXIT, onExit);
}
function onOutputData(event)
{
air.Introspector.Console.log("Got: ", process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable));
}
function onErrorData(event)
{
air.Introspector.Console.log("ERROR -", process.standardError.readUTFBytes(process.standardError.bytesAvailable));
}
function onExit(event)
{
air.Introspector.Console.log("Process exited with ",event.exitCode);
$("#output").html("Start");
}
function onIOError(event)
{
air.Introspector.Console.log(event.toString());
}
$(function()
{
$("#start").click(function()
{
air.Introspector.Console.log("START");
launchProcess();
});
});
the c program is quite long, and here i post only the main part
int main( int argc, char *argv[])
{
//! get shell commands for init
// echo shell commands
for( int count = 0; count < argc; count++ )
{
cout << " argv[" << count << "] "
<< argv[count];
}
// handle data
intDevice = (int)(argv[1][0] - '0');
intChannel = (int)(argv[2][0] - '0');
intChannel -= 1;
intSymbolRate = atoi(argv[3]);
//! class function calls
useDll CanFunction;
try
{
CanFunction.initProg();
CanFunction.ecuScan();
CanFunction.openSession();
CanFunction.readECU();
CanFunction.stopProg();
return 0;
}
//! exception handling
catch(int faultNumber)
{
....
}
}
First I used only the onExit listener and everything works fine. After I used start conditions adobe air only responses if i call no class functions except the CanFunction.initProg() and the onExit function was called but skipped the jQuery command to create the link. If I add the class function calls, the c program is called and the json database created but Adobe Air doesnt received any responses. The json database is still created. This confuses me.
My c program uses some *.dll files to communicate with the bus so i could imagine that it is a windows problem. But it is still weird.
Has anybody an idea why adobe air communication doesnt work with my c program if i call my class functions or why the jQuery command is skipped?
Or is there a better solution to call a c++ exe from adobe air?
i am working on CDT eclipse plug in development, i am trying to get the list of sources files which exist in eclipse project explorer using CDT code using following code ,which results null.
Case1:
IFile[] files2 = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(new URI("file:/"+workingDirectory));
for (IFile file : files2) {
System.out.println("fullpath " +file.getFullPath());
}
Case2:
IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(getProject().getRawLocationURI());
for (IFile file : files) {
System.out.println("fullpath " +file.getFullPath());
}
Case3:
IFile[] files3 = ResourceLookup.findFilesByName(getProject().getFullPath(),ResourcesPlugin.getWorkspace().getRoot().getProjects(),false);
for (IFile file : files3) {
System.out.println("fullpath " +file.getFullPath());
}
Case4:
IFolder srcFolder = project.getFolder("src");
Case 1 ,2,3 giving me output null, where i am expecting list of files;
in Case 4: i am getting the list of "helloworld/src" files, but i am expecting to get the files from the existing project mean main root ,ex:"helloworld"
please suggest me on this.
You can either walk through the worspace resources tree using IResourceVisitor - or you can walk through CDT model:
private void findSourceFiles(final IProject project) {
final ICProject cproject = CoreModel.getDefault().create(project);
if (cproject != null) {
try {
cproject.accept(new ICElementVisitor() {
#Override
public boolean visit(final ICElement element) throws CoreException {
if (element.getElementType() == ICElement.C_UNIT) {
ITranslationUnit unit = (ITranslationUnit) element;
if (unit.isSourceUnit()) {
System.out.printf("%s, %s, %s\n", element.getElementName(), element.getClass(), element
.getUnderlyingResource().getFullPath());
}
return false;
} else {
return true;
}
}
});
} catch (final CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Note there may be more source files then you actually want (e.g. you may not care system about headers) - you can filter them by checking what the underlying resource is.